Problem mit strcmp



  • Hallo,

    in folgendem Code:

    char **array;
        array = malloc(sizeof(char *));
        int i=0;
        for(;;i++) {
            array = realloc(array,i+1);
            array[i] = malloc(10*sizeof(char));
    
            fgets(array[i],10,stdin);        
    
            printf("%s",array[i]);
            if(strcmp(array[i],"end") == 0)
                break;
        }
        for(int j;j<i;j++)
            printf("%s\n",array[j]);
    

    bricht die Schleife nie ab, auch wenn "end" eingegeben wird. Was habe ich falsch gemacht?

    Danke!



  • Abgesehen von der wutzigen foo = realloc(foo, ...);-Geschichte, die dir um die Ohren fliegt, wenn realloc mal schiefgeht? fgets schreibt das Newline-Zeichen in den Buffer. Der richtige Vergleich ist

    if(strcmp(array[i], "end\n") == 0)
    

  • Mod

    Das realloc ist schon einmal falsch, da möchtest du wohl noch mit sizeof(char*) multiplizieren.

    Das fgets entfernt keinen Whitespace! In der Eingabe wird mindestens noch ein Zeilenumbruch stehen, also "end\n". Daher schlägt der Vergleich fehl.

    edit: Zu langsam. Ich war zu begeistert, dass hier mal jemand das malloc nicht castet, dass ich minutenlang auf den Code gestarrt habe 🙂 .



  • Es muss auch

    realloc(array,(i+1)*sizeof(char *));
    

    sein



  • for(int j;j<i;j++)
            printf("%s\n",array[j]);
    

    Hierbei ist j uninitialisiert.



  • Das hättest du auch schneller herausfinden können. Nutze einfach den Debugger! Haltepunkt setzen, schauen, was wirklich im Puffer steht, Fehler beheben. 💡



  • Danke!

    (außerdem fehlte noch, dass ich "int j = 0" in der zweiten Schleife schreiben muss :))



  • Wutz schrieb:

    Hierbei ist j uninitialisiert.

    ... und die Warnungen vom Compiler beachten



  • eine Warnung habe ich nicht erhalten 😉



  • und wenn wir schon dabei sind:
    "j < = i" 🙂



  • Ich mach mal nen Gegenvorschlag:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void) {
      char (*array)[10] = NULL;
      int i = 0;
    
      do {
        char (*tmp)[10] = realloc(array, (i + 1) * sizeof(char[10]));
    
        if(tmp == NULL) {
          free(array);
          array = NULL;
          break;
        }
    
        array = tmp;
    
        if(NULL == fgets(array[i], 10, stdin)) {
          break;
        }
    
        printf("%s", array[i]);
      } while(strcmp(array[i++], "end\n") != 0); /* Ui, endlich mal ein Anwendungsfall für Postinkrement :D */
    
      if(array != NULL) {
        int j;
    
        for(j = 0; j < i; ++j) {
          puts(array[j]);
        }
      }
    
      free(array);
    
      return 0;
    }
    

    Natürlich wäre es effizienter, die Allokation in größeren Blöcken durchzuführen, aber das sei dir als Übungsaufgabe überlassen.



  • Ich weiß, ich sollte die Fehlerbehandlung nicht weglassen :). Danke für deine Mühe, einen sauberen Text zu schreiben :).



  • qwert_zuiopü schrieb:

    eine Warnung habe ich nicht erhalten 😉

    Dann erhöhe den Warnlevel vom Compiler (alles).
    Beachte und behebe die Warnungen.


  • Mod

    DirkB schrieb:

    qwert_zuiopü schrieb:

    eine Warnung habe ich nicht erhalten 😉

    Dann erhöhe den Warnlevel vom Compiler (alles).
    Beachte und behebe die Warnungen.

    Das ist ein "Feature" vom GCC. Er hat vermutlich auf O0 compiliert, da hat das j einen definierten Wert. Daher bekommt man erst mit Optimierungen eine Warnung.



  • Also ich erhalte auch mit O2 keine Warnung.



  • Es scheint so, als würde jetzt der Wert von j automatisch die 0 zugewiesen bekommen.



  • qwert_zuiopü schrieb:

    Also ich erhalte auch mit O2 keine Warnung.

    Dann hast du Warnungen vermutlich deaktiviert. Setz mal folgende Flags: -Wall -Wextra -pedantic-errors -std=c99

    (oder besser -std=c11 bzw. -std=c1x wenn du einen aktuellen GCC hast)



  • Danke, so funktioniert es.



  • Weil es sich immer noch auf das selbe Beispiel bezieht, schreibe ich meine nächste Frage nochmal hier rein:

    char **array;
        array = malloc(sizeof(char *));
        int i=0;
        for(;;i++) {
            array = realloc(array,(i+1)*sizeof(char *));
            array[i] = malloc(10*sizeof(char));
    
            if(fgets(array[i],10,stdin) == NULL)
                return -1;
    
            if(strcmp(array[i],"end\n") == 0)
                break;
        }
    
        printf("Ihre Eingaben:\n");
        for(int j = 0 ;j<=i;j++)
            printf("%s",array[j]);
    
        qsort(&array[0],i,10*sizeof(char),qsort_strcmp);
    
        printf("\n\nSortiert:\n");
        for(int j = 0 ;j<=i;j++)
            printf("%s",array[j]);
    
        for(int j=0;j<=i;j++)
            free(array[j]);
    
        free(array);
    

    mit

    int qsort_strcmp(const void *left, const void *right) 
    { 
        return strcmp(left, right); 
    }
    

    Scheinbar rufe ich die qsort-Funktion falsch auf. Was mache ich genau falsch?


  • Mod

    Das qsort ruft die Vergleichsfunktion mit Zeigern auf die Elemente auf. Deine Elemente sind hier Zeiger auf deine Zeichenketten. Also bekommt qsort_strcmp Zeiger auf Zeiger auf die Zeichenketten. strcmp erwartet aber die Zeiger auf die Zeichenketten.

    Zudem ist natürlich falsch, wie du qsort an sich aufrufst, denn deine Elemente haben Größe sizeof(char*) nicht Größe 10 (sizeof(char) ist übrigens per Definition immer 1 und &array[0] ist als Funktionsparameter das gleiche wie einfach nur array).


Anmelden zum Antworten