Textzeile parsen



  • Guten morgen,
    ich hoffe, dass diese Frage hier noch nicht zu oft gestellt wurde:

    ich habe mit "getLine" eine Zeile aus einem Stream eingelesen und möchte diese Zeile nun gern parsen.

    In der Datei stehen Zeilen der folgenden Art

    Befehl Param1 Param2 Param3 ...

    jeweils durch ein Leerzeichen voneinander getrennt.
    DIe Positionen des ersten Leerzeichens finde ich schon. Aber wie kann ich die einzelnen Substrings beispielsweise in eine

    struct Befehl{
    string befehl;
    string param1;
    string param2;
    };

    schreiben?

    Im Voraus bereits vielen Dank
    Jochen



  • JoKl schrieb:

    DIe Positionen des ersten Leerzeichens finde ich schon.

    Wenn du eine Stelle hinter dieser Position weitersuchst, findest du auch die nächsten Leerzeichen in deiner Eingabe 😉

    Aber wie kann ich die einzelnen Substrings beispielsweise in eine [struct] schreiben?

    Du kannst dir mittels substr() die jeweiligen Teile aus der Eingabezeile rausgreifen (nachdem du Anfangs- und Endposition berechnet hast) und einfach den Elementen des struct zuweisen:

    struct command
    {
      string befehl;
      vector<string> params;
    }
    
    ...
    string line;
    command cmd;
    getline(file,line);
    size_t pos=line.find(' '),pos2;
    cmd.befehl=line.substr(0,pos++);
    while(pos!=string::npos)
    {
      pos2=line.find(' ',pos);
      cmd.params.push_back(line.substr(pos,pos2-pos));
      pos=pos2+1;
    }
    


  • vielleicht ist die Lösung übertrieben, aber Boost::Spirit ist wie geschaffen für sowas.

    Man definiert nur in EBNF die Grammatik und kann das dann sicher und einfach parsen lassen.



  • Ich bin Fan von

    strtok
    

    .
    Schau dir mal das Beispiel in der MSDN an, wie die einen String zerstückeln.



  • ich bin fan von boost::tokenizer, das ist zwar nicht so mächtig wie boost::spirit.
    aber in so einem fall einfacher zu benutzen. boost::spirit wird hier wohl eh nur 1/20 aller C++'ler richtig benutzen können 😃 ich zähl nich dazu ^^



  • @ Alle

    macht's doch nicht so kompliziert. von strtok bis spirit ist für diese Aufgabe alles mit Kanonen auf Spatzen geschossen. Einfach den Befehl, so wie er da steht, einlesen. Man muss noch nicht mal vorher die Zeile mit getline einlesen. Etwa so geht's

    Stream in; // z.B. ifstream 
        Befehl b;
        in >> b.befehl >> b.param1 >> b.param2;
    

    idealerweise packt man das Code-Segment in einen Streaming-operator, und kann ggf. noch bis zum Ende der Zeile alles überlesen, falls da irgendein Kommentar oder so stehen sollte.

    std::istream& operator>>( std::istream& in, Befehl& b )
    {
        return (in >> b.befehl >> b.param1 >> b.param2).ignore( 9999, '\n' );
    }
    // Anwendung:
        Stream in; // z.B. ifstream 
        Befehl b;
        if( in >> b )
            // Befehl b ohne Fehler gelesen
    

    Gruß
    Werner


Anmelden zum Antworten