C String extrahierung



  • Hallo zusammen,
    ich habe ein Problem mit einer String-Extrahierung, dabei liegt folgende Datenstruktur vor, die ich zeilenweise aus einer Datei einlese. Die Datenstruktur sieht so aus:

    <doc id=djlksf9i>
    <title>Mein Titel</title>
    <autor>Peter Muster</autor>
    </doc>
    

    Mein Ziel ist es den String zwischen <title> und </titel> in eine Variable zu schreiben. Hat jemand eine Idee, wie man das am einfachsten mit C macht?

    Alle versuche mit strstr und strncpy usw. schlugen fehl. Ich habe bisher folgendes Versucht:

    char* startString = "<title>";
    char* endString = "</title>";
    char* extractStart = NULL;
    char* extractEnd = NULL;
    
    extractStart = strstr(line, startString); // line ist eine Zeile der eingelesenen Datein
    extractEnd = strstr(line, endString);
    

    Das ergibt mir nun den Output:

    extractStart = "<title>Mein Titel</title>"
    extractEnd = "</title>"
    

    Jemand eine Idee, wie ich weiterfahren könnte?
    Wäre super. Danke.



  • Bist du dir sicher, dass du keinen echten XML-Parser benutzen willst?

    Ansonsten kannst du das ganze so anstellen:

    char const *const startString = "<title>";
    char const *const endString = "</title";
    
    char const *start = strstr(line, startString);
    if(!start) {
      // ...
    }
    start += strlen(startString);
    if(*start == '\0') {
      // ...
    }
    char const *end = strstr(start, endString);
    if(!end) {
      // ...
    }
    size_t len = end - start;
    char *content = malloc(len + 1);
    if(!content) {
      // ...
    }
    memcpy(content, start, len);
    content[len] = '\0';
    

    // ... sind die Fehlerfälle.



  • Dies ist nicht schwer. strstr+strncpy war schon der richtige Weg, wahrscheinlich haperte es an deiner konkreten Umsetzung.

    typedef struct {
      char *schluessel,*wert;
    } Bezug;
    
    int ermittleWerte(const char *s,const char* const* k,Bezug ***w)
    {
      int i=0;
      *w=0;
      while( *k )
      {
        char *a=s,*e,
        *x=strcat(strcat(strcpy(malloc(strlen(*k)+3),"<"),*k),">"),
        *y=strcat(strcat(strcpy(malloc(strlen(*k)+4),"</"),*k),">");
        while( (a=strstr(a,x)) && (e=strstr(a,y)) && a<e )
        {
          *w=realloc(*w,++i*sizeof*w);
          (*w)[i-1]=malloc(sizeof***w);
          (*w)[i-1]->schluessel=*k;
          (*w)[i-1]->wert=memcpy(calloc(1,e-a-strlen(x)+1),a+strlen(x),e-a-strlen(x));
          a=e;
        }
        free(y);
        free(x);
        ++k;
      }
      return i;
    }
    

    sollte funktionieren für ein beliebige Anzahl von Werten in deinem String, z.B.

    ...
      char *str="<title>ein Titel <abc></title><autor>ein Autor <xyz></autor>";
      const char *tags[]={"title","autor",0};
      Bezug **b;
      int i=ermittleWerte(str,tags,&b);
      printf("\n%d Werte ermittelt.",i);
      while( i-- )
        printf("\n%s:=%s",b[i]->schluessel,b[i]->wert),free(b[i]->wert),free(b[i]);
      free(b);
    ...
    


  • Hallo,

    rüdiger schrieb:

    Bist du dir sicher, dass du keinen echten XML-Parser benutzen willst?

    Ich werde wohl libxml2 einbinden, trotzdem störte es mich, dass ich die Strings ohne XML-Parser nicht extrahieren konnte. Ich werde mich wohl etwas ausführlicher mit den Funktionen malloc() und memcpy() auseinandersetzen müssen.

    Dein Code funktioniert einwandfrei. Das hat für mich einige Dinge punkto String-Handling in C geklärt. Danke für Deine Hilfe!



  • cflorian schrieb:

    Ich werde wohl libxml2 einbinden, trotzdem störte es mich, dass ich die Strings ohne XML-Parser nicht extrahieren konnte.

    Gewöhn dich daran, C bringt nur rudimentäre Mittel zur Stringbearbeitung mit. Das ganze wird dann noch einmal anstrengender, weil man Strings mit variabler Länge jedes mal selbst bauen muss. Die Zeilen 16 bis 22 würde man in einer abstrakteren Sprache etwa so formulieren:

    content = line.substring(start, len)
    

    Damit will ich zeigen, dass man sowas nur in C machen sollte, wenn es wirklich nicht anders geht.

    cflorian schrieb:

    Ich werde mich wohl etwas ausführlicher mit den Funktionen malloc() und memcpy() auseinandersetzen müssen.

    Das ist nicht schwer. Nur mit malloc() soll man sich nicht zu sehr anfreunden, das ist eine Schnittstelle zum Betriebssystem und wahrscheinlich eher teuer.

    Der Interpreter für meinen Pseudocode oben wird z.B. ein implizites malloc() für den neuen String machen müssen. Aber einer der Vorteile von C ist gerade, dass man malloc() nicht aufrufen muss, wenn man nicht will.
    🙂


Anmelden zum Antworten