Parser... ist noch zu unelegant...



  • Moin Moin!

    Ich komme allein leider nicht mehr weiter.
    Ich habe einen Parser geschrieben welcher mir ein Config-File entziffert.
    Format:

    NAME_DES_WERTES [wert]

    Es funktioniert auch recht gut.
    Das Problem ist nur, das der Zwischenraum zwischen dem Namen des einzulesenden Wertes entweder ein " " oder ein "\t" sein kann. Oder beides. Das Programm akzeptiert hinter dem NAMEN nur ein " " und vor dem WERT nur ein "\t".
    Das ist natürlich sehr unelegant.
    Ich weiss nicht wie ich eine Oder-Abfrage o.ä. einbauen soll bzw. ob es einen andern Weg gibt.

    char cDataBuffer[256];
    char* token;
    int wert1,wert2;
    
    while(!InStream.eof)
    {
    InStream.getline(cDataBuffer, sizeof(cDataBuffer));
    
    while(cEndControll !=0)
    {
    
    token = strtok(cDataBuffer, " ");
    
    if(token && strcmp(token,"WERT1")==0)
    {
    token = strcmp(0,"\t[]");
    wert1 = token;
    }
    
    else if(token && strcmp(token,"WERT2")==0)
    {
    token = strcmp(0,"\t[]");
    wert2 = token;
    }
    
    // usw.
    
    cEndControll = strtok(0,"\n");
    }
    }
    

    Danke und schöne Grüsse,

    Lutz



  • schau dir mal die std::string klasse an
    was du da programmierst ist eine mischung aus c++ (streams) und c (char-arrays bzw. zeiger). in C++ benutzt man std::string für zeichenketten, die unterstützt dann auch methoden wie den ==operator und find().



  • In c++ benutzt man kein std::string! Man kann es verwenden, muss man aber nicht.
    In manchen Sachen ist std::string sehr umkonfortable!!!

    @SecretAgentMan
    Wenn du nicht weisst wie man eine ODER(||) Abfrage realisieren kannst, empfehle ich dir einen Grundlagen-Tutorial durchzuarbeiten. Ansonsten solltest du deine Algorithmen im Kopf oder besser auf dem Papier durchspielen. So kommst man fast immer auf die Lösung des Problems und erskennst auch zukünftige Probleme.

    Mfg Maxim



  • In manchen Sachen ist std::string sehr umkonfortable!!!

    Falsch.



  • Maxim_2005 schrieb:

    In c++ benutzt man kein std::string!

    <IRONIE> Ja klar. </IRONIE>



  • Hi,

    Ich weiss sicher wie mann eine ODER-Abfrage macht. Wegen sowas würde ich keinen Belästigen, denn das steht ja nun wirklich überall. Auch hab ich es im Kopf und auf dem Papier durchgespielt. Sonst würde der Parser auch nicht soweit laufen wie er jetzt läuft. denn er funktioniert ja, wenn man hinter dem Wertenamen ein " " und dannach ein "/t" im Skript zu stehen hat.
    Mir geht es darum wie ich es in diesem speziellen Fall mache, denn Folgendes funktioniert ja leider nicht:

    token = strtok(cDataBuffer, " ") || strtok(cDatabuffer, "/t");

    oder

    token = strtok(cDataBuffer, " " || "/t")

    Auf die Idee mit std:string bin ich auch schon gekommen, doch da tauchen andere Schwierigkeiten auf, die sich mittels char-Array erstmal (zumindest für mein Verständnis) schneller lösen lassen.

    Grüsse,

    Lutz



  • ich würde einer string klasse immer einen char array vorziehen!



  • ajax schrieb:

    ich würde einer string klasse immer einen char array vorziehen!

    Ja, kannste ja machen, werd ich beim nächsten mal evtl. auch.
    Trotzdem Helfen mir solche Antworten nicht wirklich weiter.



  • Also irgendwie machst du da komische Sachen. Erstmal, wie richtig gesagt wurde, sollte man std::string benutzen. Die ist nicht aus Jux und Dollerei im ISO-Standard drin, sondern hat einen besonderen Grund. Schon alleine um keine Bufferoverflows u.ä. zu verursachen. Tagtäglich liest man auf heise.de von neuen Sicherheitslücken nur weil die Leute keine sichereren C++ Techniken benutzen, obwohl das ganze nun wirklich heute standard ist.

    So, um noch eines drauf zu setzen: Du könntest Regex benutzen, um solche Aufgaben zu lösen. Regex ist zwar in dem Sinne kein Parser, aber du kannst damit Texte analysieren und Manipulieren. Boost hat eine Regex-Lib die auch im TR1 drin ist.
    http://www.boost.org/libs/regex/doc/index.html
    Tutorial: http://www.regenechsen.de/phpwcms/index.php?regex_allg

    Dann gibt es noch folgendes: eine Bibliothek die sich Spirit nennt. Diese ist speziell dafür gedacht, damit man sich Parser bauen kann. Dabei wird Metaprogrammierung benutzt. D.h. du definierst den Parser mit C++ Code, und der Compiler baut dir nen Parser zusammen.

    Für einen Einstieg gibts in unserem C++ Magazin auch einen Spirit-Artikel.
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-139383.html
    Vielleicht lest du ihn dir unverbindlich durch und vielleicht ist es ja etwas, was dir weiter hilft?



  • SecretAgentMan schrieb:

    Ich habe einen Parser geschrieben welcher mir ein Config-File entziffert.
    Format:

    NAME_DES_WERTES [wert]

    @Alle
    Die IO-Bibliothek von C++ wird gnadenlos unterschätzt. Das ist doch kein kompliziertes Parser-Problem, bei dem man 'zig Alternativen an Zeichenfolgen hat.

    Hallo Lutz,
    lies doch einfach die Variblen so direkt aus dem File, in dem Format, wie Du es oben beschrieben hast. Etwa so:

    #include <fstream>
    #include <string>   // std::string; getline
    
    struct Wert
    {
        friend std::istream& operator>>( std::istream& in, Wert& wert )
        {
            char klammerAuf;
            std::getline( in >> wert.m_name >> klammerAuf, wert.m_value, ']' );
            return in;
        }
    
        std::string m_name;
        std::string m_value;
    };
    
    int main()
    {
        using namespace std;
        ifstream cfg("input.txt");
        Wert w1, w2;
        cfg >> w1 >> w2; // liest 2 Werte aus 'input.txt'
    
        return 0;
    }
    

    Um die Spaces und Tabs (White-Spaces) brauchst Du Dir auch keine Sorgen machen. Die Default-Einstellung ist so, dass diese als Trenner zwischen Worten und Zahlen dienen und ansonsten immer überlesen werden.
    Es muss nur sichergestellt sein, dass zwischen NAME_DES_WERTES und '[' mindestens ein White-Space steht und NAME_DES_WERTES keine White-Spaces enthält.

    Gruß
    Werner



  • Hi Werner!

    Danke, das wird helfen. Werde es am Montag ausprobieren. Hatte mir das viel komplizierter vorgestellt, da ich mit std:string noch keine Erfahrungen hab.
    Aber wenn das sooo "einfach" geht, na dann... Gewusst wie.

    Danke und gute Nacht. zzz zzz zzz


Anmelden zum Antworten