Parsen eines Strings unter C

Humpelstielzchen

Grünschnabel
Hallo,

ich bin ganz neu hier und hatte gehofft, dass ihr mir vielleicht helfen könnt.
Aufgabe ist es, einen französichen Verbendeklinierer zu bauen. D.h. der Nutzer gibt ein Verb ein und das Programm spuckt die komplette Deklination in Presents und Imparfait wieder aus. Dafür muss ich die einzelnen Zeilen einer Config-Datei parsen, wo die Endungen etc abgespeichert sind. Und an diesem Parsen scheitere ich gerade, da eine einzelne Zeile nur aus einer Zahl und ansonsten Wörtern besteht.
z.B. "6 present er$ er$ e es e ons ez ent"
Mit fscanf und sscanf habe ich es schon versucht, aber die einzelnen Wörter werden durch das Fehlen des '\0' ja nicht erkannt. Mit regulären Ausdrücken kenne ich mich nun gar nicht aus. Gibt es da vielleicht noch ne Möglichkeit? Oder muss ich das wirklich stur von Hand mittels getc parsen?
Vielen Dank schon mal für die Hilfe.
Gruß...
 
Hallo,

ich hoffe ich habe dein Problem richtig verstanden. Jemand gibt ein Verb ein und du suchst in deiner Datei ob das Verb vorhanden ist um die Deklination auszuspucken.

hier eine kleine Quick and Dirty Anleitung damit du dir nicht jeden Buchstaben per getc suchen musst.

1.) über die IOStream LIB Datei reinladen
2.) dann mit getline die jeweilige Zeile
3.) und per CString.mid(...) schauen ob es dein Value ist in der Zeile

ich hoffe das reicht als Anstoß.

Grüße
R.
 
Ich hoffe, du hast mich richtig verstanden, dass wir in C programmieren, nicht in C++. Per getline lese ich die einzelnen Zeilen auch ein, alles kein Problem,nur wie gesagt,dass Parsen.
Die Verben werden in der config datei nicht gespeichert. Nur Verbfamilien, und woran man sie erkennen kann. Also z.B. im oberen Beispiel:
6 present er$ er$ e es e ons ez ent

-> Verbfamilie 6
-> Zeit: Präsents
-> Endung: er
-> Stamm: ohne er
und dann die Endungen.

Dafür verwende ich Structs, wo ich diese Informationen speichere. Nur um die ganzen Daten im Struct zu speichern, muss ich den String erstmal parsen.

Versucht habe ich das mit sscanf:

sscanf(*line_ptr,"%d %s %s %s %s %s %s %s %s %s\n",
&sconj.id,
&sconj.time,
&sconj.expr_sel,
&sconj.expr_cut,
&sconj.decl[0],
&sconj.decl[1],
&sconj.decl[2],
&sconj.decl[3],
&sconj.decl[4],
&sconj.decl[5]);

wobei, *line_ptr der Pointer zu der jeweiligen Zeile ist.
Aber,wie gesagt, dies geht ja nun leider nicht so einfach...
Gruß
 
Hallo,

sorry habe ich völlig überlesen. Dann würde ich mal probieren mit memcmp bzw.strncmp zu arbeiten.

Wenn am Anfang immer die Zahl steht diese einfach aus dem pointer rausnehmen bzw. vor deinen String setzen und dann den memcmp machen.

Eingabe: presente
Zeile: 6 presente ......

Einfach die 6 vor dein char* setzen
Code:
strcpy(lpszText,"6 ");
strcat(lpszText, Eingabe);

dein neuer char* 6 presente

und dann per

Code:
memcmp(Zeile, lpszText, strlen(lpszText));

habe das ganze natürlich nicht getestet, müsste aber so ungefähr funktionieren.

Grüße
R.
 
strtok() ist ne coole Idee. Eigentlich genau das, was ich gesucht habe.
So wie ich, das verstanden habe, funktioniert strtok() so:

Code:
  char *ptr;

           ptr = strtok(line, " ");
          while(ptr != NULL) {
          //Token verarbeiten
          ptr = strtok(NULL, " ");
   }

Aber, wenn ich jetzt die einzelnen Token in einem Struct ablegen will, habe ich doch das Problem, dass der Pointer nur per Copy, also die Adresse übergeben wird und im Endeffekt dann überall das gleiche drin steht. Außerdem weiß ich nicht, wie ich ohne counter die richtigen felder im struct erreichen soll.
Zur Verdeutlichung ein Testprogramm, wo ich mal wieder den Fehler "Segmentation Fault" erhalte. Warum?

Code:
struct test{
  char * nom1;
  char * nom2;  
 };

 int main(){
  char * line = "nom1 nom2";
  char* ptr;
  struct test t;
  int count = 1;  
 
     
   ptr = strtok(str, " ");
   while(ptr != NULL) {
      
    if(count == 1){
      t.nom1 = ptr;
      count++;
    }

    if(count == 2){
      t.nom2 = ptr;
      count++;
    }    

     ptr = strtok(NULL, " ");
   }

   printf("nom1: %s\n",t.id);
   printf("nom2: %s\n",t.nom1);

 return 1;

 }
 
Hallo,

der "Segmentation Fault" wird durch diese Zeile verursacht:
C++:
char * line = "nom1 nom2";
Der String ist in der Form eine Konstante und sein Speicherbereich ist geschützt, womit strtok() offensichtlich Probleme hat.

Um den Counter wirst du nicht drumherumkommen, aber das könntest du auch mit einem switch erledigen. Da wird der Code etwas übersichlicher. Für die Zeichenketten in der Struktur solltest du schon Speicher reservieren und die einzelnen Tokens mit strcpy() dort hineinkopieren. Ansonsten müsstest du auch immer die eingelesene Zeile mit aufheben.
Noch ein Fehler in deinen Testprogramm: Wenn du "count" innerhalb von "if( count = ... )" inkrementierst, erledigst du mit nur einem einzigen Schleifendurchgang alle diese if-Abfragen und hast in allen Strukturelementen das Gleiche stehen.

Hier mein Version vom Testprogramm:
C++:
struct test
{
  char  nom1[20];
  char  nom2[20];  
};



int main()
{
    char   line[] = "nom1 nom2";
    char*  ptr;
    struct test t;

    int count = 1;  
      
    ptr = strtok(line, " ");

    while( ptr != NULL)
    {
        switch( count++ )
        {
            case 1: strcpy(t.nom1, ptr); break;
            case 2: strcpy(t.nom2, ptr); break;
        }

        ptr = strtok(NULL, " ");
    }

    printf("nom1: %s\n",t.nom1);
    printf("nom2: %s\n",t.nom2);

    return 0; 
}

Gruß
MCoder
 
Zuletzt bearbeitet von einem Moderator:
Zurück