strstr - Beispiel



  • Hallo,

    undzwar habe ich folgenden Code:

    #include <stdio.h>
    #include <string.h>
    
    char tracks[][80] = {
         "I left my heart in Harvad Med School",
         "Newark, Newark - a wonderful town",
         "Dancing with a Dork",
         "From here to maternity",
         "The girl from Iwo Jima",
    };
    
    void find_track(char *search_for) 
    {
         int i;
         for(i = 0; i < 5; i++) {
                 if(strstr(tracks[i], search_for))  
                          printf("Track %i: '%s'\n", i, tracks[i]);
         }
    }
    
    int main() {
        char search_for[80];
        printf("Search for: ");
        fgets(search_for, 80, stdin);
        find_track(search_for);
    
        return 0;
    }
    

    In dem Buch, indem das Beispiel steht, funktioniert die Suche. Wenn ich das Beispiel jedoch kompiliere und ausführe und "town" eingebe, wird mir kein Track angezeigt, bzw. strstr() gibt null zurück. Ich habe auch schon festgestellt woran das liegt undzwar wenn ich bei fgets(...) 5 Zeichen, die die Funktion einlesen soll, angebe, gibt mir strstr() den zweiten Track. Das heißt, fgets(..., 80, ...); liest genau 80 Zeichen ein, auch wenn nach dem 5. (als Beispiel) keine Zeichen mehr kommen und füllt den String mit '\0' auf (und deswegen kann strstr() den Substring natürlich nicht finden). Ist das soweit richtig? Und wie kann das Beispiel in dem Buch funktionieren, war das mit fgets() schon immer so oder ist das eine alte "Version", die ich habe? Und wie kann man das umgehen, gibt es eine Funktion in der "string.h" Header-File, mit der man unnötige '\0' kürzen kann?

    Danke schonmal für Antworten,
    Jaob



  • Dein Suchstring enthält ein abschließendes '\n', also "town\n" und nicht wie du denkst "town".
    Und "town\n" kann ich nirgendwo sehen.


  • Mod

    Das hat nichts mit \0 zu tun. fgets fügt ein \0 am Ende ein und das ist auch gut so, denn genau das erwarten alle Funktionen aus string.h so:
    http://en.wikipedia.org/wiki/Null-terminated_string

    Was fgets aber auch macht, ist das \n drin zu lassen, mit dem die Zeile beendet wurde. Da dieses in deiner Titelsammlung nicht vorkommt, wird nichts gefunden.

    Du suchst wohl eher:

    scanf(" %80[^\n]", search_for);
    


  • Achso, dankeschön für die Erklärungen. Das macht natürlich Sinn :D. scanf() wurde in dem Beispiel extra nicht genutzt, da theoretisch auch der Suchbegriff aus n-vielen Wörtern bestehen könnte..



  • Jaob schrieb:

    scanf() wurde in dem Beispiel extra nicht genutzt, da theoretisch auch der Suchbegriff aus n-vielen Wörtern bestehen könnte..

    Genau dafür ist der Formatspecifier [ da.


    79[^\n] bedeztet: Lese solange bis ein \n auftaucht, aber maximal 79 Zeichen.

    Welches Buch hast du denn da?



  • Aus der Head First Reihe das Buch zu C (auf Englisch).

    Das mit [^\n] wird auch einige Seiten später (nach dem Beispiel) erklärt , da habe ich schon wieder zu schnell rumexperimntiert.


  • Mod

    Ach, bei meinem scanf-Beispiel muss 79 stehen, wie DirkB schon zeigte, nicht 80. Ich komme da immer durcheinander, welche Funktionen das '\0' mitzählen und welche nicht.



  • Hallo, ich hab nochmal eine Frage:

    fscanf(in, "%79[^\n]\n", line)
    

    Ich verstehe "%79[^\n]\n" nicht so ganz. Es werden maximal 79 Zeichen bis zum '\n' eingelesen, aber warum steht danach nochmal '\n'? Heißt das, fscanf soll maximal 79 Zeichen bis zum Zeilenumbruch einlesen und in line speichern und danach den eig. Zeilenumbruch einlesen, aber nicht speichern?

    Danke schonmal für Antworten,
    Jaob


  • Mod

    Wo hast du das her?

    Heißt das, fscanf soll maximal 79 Zeichen bis zum Zeilenumbruch einlesen und in line speichern und danach den eig. Zeilenumbruch einlesen, aber nicht speichern?

    Nein, nicht ganz. Aber vermutlich glaubte der Autor dies selber. Whitespace im Formatstring (also unter anderem auch newlines) bedeutet, dass scanf so viel Whitespace liest wie möglich und diesen verwirft. Es wird also bis zum nächsten newline gelesen und danach aller folgender Whitespace verworfen, bis ein non-Whitespace oder Streamende gefunden wird.



  • A single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none).

    http://www.cplusplus.com/reference/cstdio/fscanf/



  • Das kann man auch mit einem Leerzeichen machen. Darum hat SeppJ ja auch ein Leerzeichen vor dem % eingefügt

    fscanf(in, " %79[^\n]", line)	
                ^ da
    

Anmelden zum Antworten