Probleme mit Funkionen aus string.h



  • Hallo,

    ich habe momentan schwere Probleme mit einigen Funktionen aus string.h:

    Wenn ich folgenden Code ausführe (auf Grund der Plagiatsaffäre: http://www.java2s.com/Code/C/String/Sequentiallytruncatestringifdelimiterisfound.htm)

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
      //char str[] = "The summer soldier, the sunshine patriot";
      char* str = "The summer soldier, the sunshine patriot";
      char *p;
    
      p = strtok(str, " ");
      printf("%s", p);
      do {
        p = strtok('\0', ", ");
        if(p) printf("|%s", p);
      } while(p);
    
      return 0;
    }
    

    bekomme ich IMMER einen Speicherzugriffsfehler.
    Hier mal das, was gdb mir dazu sagt:

    user@romulus:~/cWorkspace/Test/Debug$ ./Test
    Speicherzugriffsfehler
    user@romulus:~/cWorkspace/Test/Debug$ gdb Test
    # [... bla bla bla, GNU Krams ...]
    Reading symbols from /home/user/cWorkspace/Test/Debug/Test...done.
    (gdb) start
    Temporary breakpoint 1 at 0x40056c: file ../Main.c, line 19.
    Starting program: /home/user/cWorkspace/Test/Debug/Test
    Temporary breakpoint 1, main () at ../Main.c:19
    19 char* str = "The summer soldier, the sunshine patriot";
    (gdb) n
    22 p = strtok(str, " ");
    (gdb) n

    Program received signal SIGSEGV, Segmentation fault.
    strtok () at ../sysdeps/x86_64/strtok.S:190
    190 ../sysdeps/x86_64/strtok.S: No such file or directory.
    in ../sysdeps/x86_64/strtok.S
    (gdb) q

    Ähhh ja, okay, verstehe ich nicht, warum 🙂 Naja, gut, er findet die Datei nicht...
    Seltsamer Weise läuft alles wie erwartet, wenn ich den String mit

    char str[]
    

    angebe. Warum denn das auf einmal?!

    Ich hoffe mir kann jemand helfen 😃



  • Weil

    char *str = "foo";
    

    einen Zeiger auf ein Stringliteral definiert (und dabei den cv-Qualifier wegschmeißt, was man sein lassen sollte), während

    char str[] = "foo";
    

    ein Array auf dem Stack anlegt, das ausreichend groß ist, "foo" zu fassen und "foo" in dieses Array schreibt. Im Array darfst du rumschreiben, im String-Literal nicht - und strtok schreibt im ihm übergebenen Speicherbereich rum.

    Warnt der Compiler eigentlich nicht bei der Zeigerzuweisung? Merke: Jedes mal, wenn ein String-Literal einem char zugewiesen wird, tötet Gott ein niedliches, kleines Kätzchen auf unnötig grausame Weise.* So geht das richtig:

    char const *str = "foo";
    

    ...dann meckert der Compiler auch gleich, wenn man damit Unfug anstellen will.

    angegebener Link schrieb:

    p = strtok("The summer soldier, the sunshine patriot", " ");
    

    Äh...nein. Einfach nein. So was ist nicht erlaubt, und ich würde eine Seite, die solchen Code lehrt, nicht weiter benutzen. Das ist ja schlimmer als JW.



  • Jepp. Katzen sind hiermit ausgestorben. RIP 🕶

    Ein Pointer ist halt etwas anderes wie ein Array. Progammiert
    man so etwas mal in Assembler (oder hat einen Compiler mit Assembler-
    Output) wird das sofort klar.



  • #include <stdio.h>
    #include <string.h>
    
    int main() {
    	char *str = strdup("The summer soldier, the sunshine patriot");
    
    	char *p = strtok(str, " ");
    
    	printf("%s", p);
    
    	while ((p = strtok('\0', ", ")) && p) {
    		printf("|%s", p);
    	}
    
    	free(str);
    
    	return 0;
    }
    


  • kjhkjhk schrieb:

    strdup(...)
    

    Was ist denn das?



  • mngbd schrieb:

    kjhkjhk schrieb:

    strdup(...)
    

    Was ist denn das?

    Ein Blick in mein rtfm sagt mir:

    The strdup function creates a duplicate copy of the string pointed to by src and returns a pointer to the new copy. For strdup, the memory for the new string is obtained by using the malloc function and can be freed using the free function.

    Das tückische bei strtok() ist, es verändert den Quellstring 👎



  • Scheppertreiber schrieb:

    Ein Blick in mein rtfm sagt mir:
    ...

    Dein rtfm hätte ich gerne. Auszug aus dem C99-Index:

    ...
    strcpy function, 7.21.2.3
    strcspn function, 7.21.5.3
    streams, 7.19.2, 7.20.4.3
    ...
    

    Auch eine beherzte Volltextsuche hat nichts gefunden.
    🙂



  • Also, mein beherzter Compiler hat ein Helpfile (oje, Quellenangabe
    vergessen - jetzt muß ich Ehrenworten und ab in die Badewanne 🙄 )



  • Es handelt sich um eine POSIX-Funktion. Siehe http://pubs.opengroup.org/onlinepubs/9699919799/functions/strdup.html



  • Scheppertreiber schrieb:

    jetzt muß ich Ehrenworten und ab in die Badewanne 🙄

    Als ob ich in der Not nichtmal die man-Tags verwenden könnte (man: strdup). Dort steht aber, dass das eine POSIX-Erweiterung ist. Bitte zwei Etagen höher absteigen.



  • char *strdup(const char *str) {
    	char *p = NULL;
    
    	if (str)
    		if (p = malloc(sizeof(char) * (strlen(str) + 1)))
    			strcpy(p, str);
    
    	return p;
    }
    

    Stellt euch nicht so an. Kann man sich auch selber basteln.



  • --- schrieb:

    Stellt euch nicht so an. Kann man sich auch selber basteln.

    Da mach ich lieber ein Array draus, spart Tipparbeit.
    🙂



  • mngbd schrieb:

    --- schrieb:

    Stellt euch nicht so an. Kann man sich auch selber basteln.

    Da mach ich lieber ein Array draus, spart Tipparbeit.
    🙂

    Lässt sich aber nicht reallozieren.



  • --- schrieb:

    Lässt sich aber nicht reallozieren.

    Und an die Wand hängen kann man's auch nicht.



  • KoenigGunther schrieb:

    p = strtok('\0', ", ");
    

    ⚠ '\0' ist etwas anderes als NULL

    '\0' ist das Zeichen mit dem Wert 0 (als Kennung für das Stringende verwendet)
    NULL ist der Wert für einen ungültigen oder nicht definierten Zeiger.



  • Vom Sinn hast du natürlich Recht, aber rein funktionell sollte beides auf das gleiche hinauslaufen.

    Schließlich ist NULL :

    #define NULL 0
    

    oder

    #define NULL ((void *) 0)
    

    Beides evaluiert letztendlich zu 0. Genau wie '\0' zu 0 evaluiert.



  • Das ist schon klar.

    Trotzdem deutet es darauf hin, das er das nicht richtig verstanden hat.



  • Vielen Dank für die vielen Antworten!
    Ich komme nicht aus der C-Welt, aber die Geschichte mit dem Array in dem ich rumschreiben darf, habe ich verstanden 😛

    1a!



  • DirkB schrieb:

    ⚠ '\0' ist etwas anderes als NULL

    Ja, das kommt von dem angegebenen Link. Ich würde das nicht so schreiben. Ich wollte nur fix ein Minimalbeispiel 🙄


Anmelden zum Antworten