<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Parsen...]]></title><description><![CDATA[<p>Ich werkel grade an einer kleinen Konsole rum und überlege, wie man eingegebene Befehle am Besten parsen kann. Testweise lasse ich Argumente gerade außer Acht und habe meinen Befehls-Parser recht einfach aufgebaut, vereinfacht:</p>
<pre><code class="language-cpp">char* input=GLOBAL.get(0); // Holt erses Argument aus Tabelle
int i=0;

while(input[i])
{
    if(input[i]&gt;='a' &amp;&amp; input[i]&lt;='z') { // Kleinbuchstaben -&gt; Großbuchstaben
        input[i] = (input[i] - 32); }
    i++;
}

     if (util::cmpstrn(input,&quot;EXIT&quot;)) exit_flag=1;

else if (util::cmpstrn(input,&quot;ECHO&quot;)) cout &lt;&lt; GLOBAL.getstrn(1) &lt;&lt; &quot;\n\n&quot;;

else if (util::cmpstrn(input,&quot;ABOUT&quot;)) {

         cout &lt;&lt; &quot;\n  Console\nVersion 0.1 Alpha&quot;
              &lt;&lt; &quot; (C) 2005. by BloodLord. All rights reserved.&quot;; }

...
</code></pre>
<p>Jetzt finde ich es aber nicht sehr schön, eine endlos lange if/else if Liste zu machen die durchlaufen wird und bin auf der Suche nach einer besseren Möglichkeit, meine sinnlosen Einfälle sind dann Dinge wie:</p>
<pre><code class="language-cpp">char **commands;

... // In commands kommt eine liste mit alle befehlen...

int lalala(const char* input) {
    // ...denen alle eine nummer zugeordnet ist...

    for(int i=0; i&lt;irgendwas; i++) {

        if(util::cmpstrn(input) return i; }

    return -1; }

void hmhmhm() {
    int temp=lalala(GLOBAL.get(0));

    switch (temp) // ...welche dann aber wiederum umständlich einer Anweisung zugeordnet wird
    {
        case -1: break;

        case 0: exit_flag=1; break;

        case 1: cout &lt;&lt; GLOBAL.getstrn(1) &lt;&lt; &quot;\n\n&quot;; break;

        ...
    }
}
</code></pre>
<p>Kann man sowas nicht etwas eleganter und funktioneller realisieren?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/118560/parsen</link><generator>RSS for Node</generator><lastBuildDate>Fri, 21 Aug 2026 14:22:26 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/118560.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 21 Aug 2005 22:58:37 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Parsen... on Sun, 21 Aug 2005 23:16:38 GMT]]></title><description><![CDATA[<p>Ich werkel grade an einer kleinen Konsole rum und überlege, wie man eingegebene Befehle am Besten parsen kann. Testweise lasse ich Argumente gerade außer Acht und habe meinen Befehls-Parser recht einfach aufgebaut, vereinfacht:</p>
<pre><code class="language-cpp">char* input=GLOBAL.get(0); // Holt erses Argument aus Tabelle
int i=0;

while(input[i])
{
    if(input[i]&gt;='a' &amp;&amp; input[i]&lt;='z') { // Kleinbuchstaben -&gt; Großbuchstaben
        input[i] = (input[i] - 32); }
    i++;
}

     if (util::cmpstrn(input,&quot;EXIT&quot;)) exit_flag=1;

else if (util::cmpstrn(input,&quot;ECHO&quot;)) cout &lt;&lt; GLOBAL.getstrn(1) &lt;&lt; &quot;\n\n&quot;;

else if (util::cmpstrn(input,&quot;ABOUT&quot;)) {

         cout &lt;&lt; &quot;\n  Console\nVersion 0.1 Alpha&quot;
              &lt;&lt; &quot; (C) 2005. by BloodLord. All rights reserved.&quot;; }

...
</code></pre>
<p>Jetzt finde ich es aber nicht sehr schön, eine endlos lange if/else if Liste zu machen die durchlaufen wird und bin auf der Suche nach einer besseren Möglichkeit, meine sinnlosen Einfälle sind dann Dinge wie:</p>
<pre><code class="language-cpp">char **commands;

... // In commands kommt eine liste mit alle befehlen...

int lalala(const char* input) {
    // ...denen alle eine nummer zugeordnet ist...

    for(int i=0; i&lt;irgendwas; i++) {

        if(util::cmpstrn(input) return i; }

    return -1; }

void hmhmhm() {
    int temp=lalala(GLOBAL.get(0));

    switch (temp) // ...welche dann aber wiederum umständlich einer Anweisung zugeordnet wird
    {
        case -1: break;

        case 0: exit_flag=1; break;

        case 1: cout &lt;&lt; GLOBAL.getstrn(1) &lt;&lt; &quot;\n\n&quot;; break;

        ...
    }
}
</code></pre>
<p>Kann man sowas nicht etwas eleganter und funktioneller realisieren?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/855734</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/855734</guid><dc:creator><![CDATA[BloodLord]]></dc:creator><pubDate>Sun, 21 Aug 2005 23:16:38 GMT</pubDate></item><item><title><![CDATA[Reply to Parsen... on Sun, 21 Aug 2005 23:06:45 GMT]]></title><description><![CDATA[<p>Du könntest eine std::map mit Strings für deine Befehle und Funktionszeiger machen. Jede Funktion kriegt dann ungefähr wie main die Argumente übergeben? Nur so ne Idee... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/855735</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/855735</guid><dc:creator><![CDATA[YASC]]></dc:creator><pubDate>Sun, 21 Aug 2005 23:06:45 GMT</pubDate></item><item><title><![CDATA[Reply to Parsen... on Tue, 23 Aug 2005 16:48:49 GMT]]></title><description><![CDATA[<p>Ich hab das mit dem MVC-Modell implementiert. Dazu hab ich ein Singleton Console und eine Basisklasse IConsoleCommand, die so aussieht:</p>
<pre><code class="language-cpp">/// Interface für Konsolenkommandos
    class IConsoleCommand
    {
    public:
	/// Gibt den Namen des Kommandos zurück
	virtual std::vector&lt;std::string&gt; getName () const = 0;

	/// Führt die Aktion aus
	virtual std::string action () = 0;

	/// Zeigt eine Beschreibung des Kommandos an, auch über --help
	virtual std::string description () const = 0;

    };
</code></pre>
<p>Console sieht so aus:</p>
<pre><code class="language-cpp">class Console : public boost::noncopyable
    {
    public:
	typedef IConsoleCommand* ConsoleCommand;
	typedef std::multimap&lt;std::string, ConsoleCommand&gt; CommandMap;

	static Console* instance ()
	{
	    return &amp;msInstance;
	}

	void registerCommand (ConsoleCommand);

	const CommandMap&amp; getCommands ()
	{
	    return mCommands;
	}

	/// Startet die Konsole
	void run ();

    protected:
	/// Konstruktor
	Console () { mRunning = false; }
	/// virtueller Destruktor
	virtual ~Console () { }
    private:
	/// Liste der bereits registrierten Konsolen-Kommandos
	CommandMap mCommands;
	/// Läuft die Konsole ? 
	bool mRunning;

	/// Singleton Instanz
	static Console msInstance;
    };
</code></pre>
<p>Und Console.cpp sieht so aus:</p>
<pre><code class="language-cpp">#include &quot;Console.hpp&quot;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;utility&gt;

using namespace Universum::UserInterface::Console;
using namespace std;

Console Console::msInstance;

void Console::registerCommand (ConsoleCommand newCommand)
{
    vector&lt;std::string&gt; names = newCommand-&gt;getName ();
    for (vector&lt;std::string&gt;::iterator i = names.begin ();
	    i != names.end ();
	    ++i)
	mCommands.insert (make_pair ((*i), newCommand));
}

void Console::run ()
{
    std::string cmd = &quot;&quot;;
    CommandMap::iterator i;
    ConsoleCommand cmd_c;

    mRunning = true;

    while (mRunning)
    {
	cout &lt;&lt; &quot;$ &quot;;
	getline (cin, cmd);

	if (cmd == &quot;exit&quot;)
	    mRunning = false;
	else if (!parse (cmd))
	    cout &lt;&lt; &quot;Kommando &quot; &lt;&lt; cmd &lt;&lt; &quot; nicht gefunden&quot; &lt;&lt; endl;
    }
}
</code></pre>
<p>Jetzt müsstest du nur noch Console::parse () und ein Kommando implementieren z.B.:</p>
<pre><code class="language-cpp">class CMDCount : public IConsoleCommand
    {
    public:
	CMDCount ()
	{
	    mCounter = 0;
	}
	virtual std::vector&lt;std::string&gt; getName () const
	{
	    return myNames(&quot;count cnt&quot;);
	}
	virtual std::string action ()
	{
	    std::string str;
	    std::ostringstream os (str);
	    os &lt;&lt; &quot;Anzahl der Aufrufe:\t&quot; &lt;&lt; ++mCounter &lt;&lt; std::ends;
	    return os.str ();
	}
	virtual std::string description () const
	{
	    return &quot;Zaehlt die Aufrufe seiner selbst&quot;;
	}
    private:
	unsigned int mCounter;
    };
</code></pre>
<p>... und das Kommando im Hauptprogramm registrieren:</p>
<pre><code class="language-cpp">Console&amp; c = *Console::instance ();
    c.registerCommand (new CMDCount);
</code></pre>
<p>Ist bestimmt auch nicht der effizienteste Weg, aber nicht so C-style wie ein Switch.<br />
Für die parse Funktion würde ich Spirit benutzen, is aber recht kompliziert (wie ich finde).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/857074</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/857074</guid><dc:creator><![CDATA[.filmor]]></dc:creator><pubDate>Tue, 23 Aug 2005 16:48:49 GMT</pubDate></item></channel></rss>