Dynamische Speicherreservierung bei Strings



  • Vielen dank ich habs 🙂
    Sehr nett von dir das du mir so geholfen hast 😉
    Danke

    -GhostfaceChilla-



  • Nochmal ne Frage 😃
    Und wzar was ist wnen ich jetzt das alles in for schleife packe, diese durchläuft 5 durchläufe, dann wird ja unter print nur das letzte Wort ausgegeben, das eingegeben wurde. Um alle auszugeben, müsste man diese dann extern in eine datei speichern und diese dann am ende wieder einlesen?Oder geht das auch anders?

    -GhostfaceChilla-



  • Du kannst das natürlich auch in der for- Schleife ausgeben.

    oder:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
      char *pc[5] = {NULL};    // pc ist jetzt ein Array von Pointern auf char
      char array[20];
      int i;
    
    // anlegen
      for(i=0;i<5;i++) {
        printf("Wort %d eingeben:", i);
        fgets(array, 20, stdin);
        pc[i] = (char *)malloc(strlen(array)+1);
        if (pc[i] != NULL)
          strcpy(pc[i], array);
      }
    //    ....
    // ausgeben
      for(i=0;i<5;i++) {
        printf("Wort %d = %sn", pc[i]);
      }
    //    ....
    
    // bereinigen  !wichtig!
      for(i=0;i<5;i++) {
        free(pc[i]);
      }
    
      return EXIT_SUCCESS;
    }
    


  • /* Woerterliste.c */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        char *pc;
        char array[20];
        int i;
    
        for(i=0; i < 5; i++){
        fgets(array, 20, stdin);
        pc = malloc(strlen(array)+1);
        strcpy(pc, array);}
    
        for(i=0; i<5; i++){
        printf("%s", pc[i]);
        }
        return EXIT_SUCCESS;
    
    }
    

    So gehts ned wo liegten der Fehler?

    -GhostfaceChilla-



  • Erst einmal solltest du deinen Code richtig einrücken. So ist das doch unübersichtlich!

    Was du offenbar willst ist nicht das was du tust. char *pc ist für einen String! In der ersten for-Schleife überschreibst du immer den Zeiger auf den vorherigen String! pc[i] ist demnach ein einzelnes Zeichen und kein String und daher ist der Format-String "%s" falsch (davor sollte dich aber ohnehin dein Compiler warnen, wenn du alle Warnungen einschaltest).

    Außerdem solltest du prüfen ob malloc nicht fehlgeschlagen ist (Rückgabewert NULL).

    edit: Schau dir einfach an was DirkB gemacht hat!



  • Ok,habs jetz, danke 🙂
    Habs kapiert danke 😉

    -GhostfaceChilla-



  • Aber des bringts ja voll ned da jetzt dynamisch speicher anzufordern, da muss das array ja trotzdem nene bestimtmen Wert zugewiesen bekommen, sprich *pc[20] oder *pc[500] in meinem Fall müsste man ja dann praktisch ein *pc[800] oder höher erstellen, also geht es gar nicht ein array während der Laufzeit mehr Speicher zuzuweisen oder?

    -GhostfaceChilla-



  • Das *pc[800] ist ein Array mit 800 Zeigern auf char (Also 800 mal char *array)
    Du kannst da 800 Wörter verwalten, die (fast) beliebig lang sein können.

    Vorher war statisch Array aus Array aus char

    char woerter[800][20]; // Platz für 800 Wörter, die 19 Zeichen lang sein dürfen.
    

    jetzt dynamisch Array aus Zeigern auf char

    char *woerter[800]   // Zeiger für 800 Wörter, die (fast) beliebig lang sein dürfen.
    

    Mit einem Zeiger auf ein Array mit Zeigern auf char kannst du auch in der Anzahl der Wörter flexibel sein:

    int  anz_woerter 800; // oder 20 oder 1500 oder ...
    char **woerter; 
    woerter = (char **)malloc(anz_woerter * sizeof(*woerter)); // (fast) beliebig lange Liste mit Zeigern auf (fast) beliebig lange Wörter
    

    Wenn du noch flexibeler sein willst, nimmst du verkettete Listen.



  • Achso ah ok danke kapier endlich was es mit diesen Zeigern und dynamischem Speicher auf sich hat dake 🙂

    So in etwa?:

    /* Woerterliste.c */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        char **dyn_array[800];
        char eingabe[20];
        int i;
        int anz_woerter = 20;
    
        printf("Geben Sie Ihre  Woerter ein: \n");
        for(i=0; i<5; i++)
        {
    
            fgets(eingabe, 20, stdin);
            dyn_array[i] = (char**)malloc(anz_woerter*sizeof(*dyn_array));
            if(dyn_array != NULL)
                strcpy(dyn_array[i], eingabe);
        }
    
        for(i=0; i < 5; i++)
            printf("%s", dyn_array[i]);
    
        return EXIT_SUCCESS;
    }
    

    -GhostfaceChilla-



  • Nix verstanden.
    Dreifach Indirektionen sind wohl doch etwas viel für den Anfang, manche begreifen es nie.



  • So besser??

    /* Woerterliste.c */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        char *dyn_array[800];
        char eingabe[20];
        int i;
    
        printf("Geben Sie Ihre  Woerter ein: \n");
        for(i=0; i<5; i++)
        {
            fgets(eingabe, 20, stdin);
            dyn_array[i] = malloc(strlen(eingabe));
            if(dyn_array != NULL)
            {
                strcpy(dyn_array, eingabe);
                if( strstr(dyn_array,eingabe) != NULL)                  /* Funktioniert noch nicht, muss noch gucken */
                    printf("Wort wurde bereits eingegeben!Neueingab!"   /* wie das funktioniert arrays mit strings zu vergleichen */  
            }
            else
            {
                printf("ERROR!Kein virtueller Speicher mehr vorhanden!!");
                return EXIT_FAILURE;
            }
        }
    
        for(i=0; i < 5; i++)
            printf("%s", dyn_array[i]);
    
        return EXIT_SUCCESS;
    }
    


  • http://ideone.com/6cEE7

    Sonst wird das heute nichts mehr.



  • Als Ergänzung:
    Ich lege jetzt mal für dieses Beispiel fest, dass ein char 1 Byte und ein Zeiger 4 Byte lang ist.

    char woerter[800][20]; // Platz für 800 Wörter, die 19 Zeichen lang sein dürfen.
    

    Das sind 800 * 20 Byte = 16000 Byte.

    char *woerter[800]   // Zeiger für 800 Wörter, die (fast) beliebig lang sein dürfen.
    

    Das sind 800 * 4 Byte für die Zeiger + der Speicher für den Text. Wenn das auch 20 Zeichen sind ergibt sich 800 * 4 + 800 * 20 = 19200 Byte.

    char **woerter = (char **)malloc(anz_woerter * sizeof(*woerter)); // (fast) beliebig lange Liste mit Zeigern auf (fast) beliebig lange Wörter
    

    Da kommen noch 4 Byte für den Zeiger woerter dazu, das ergibt dann 19204 Byte

    Dynamischen Speicher nimmst du dann, wenn du zur Compilezeit nicht abschätzen kannst wie viel Daten du verarbeiten musst oder wenn die Datenmenge zu groß für den Stack ist.



  • An der Stelle sei auch mal http://www.cdecl.org/ erwähnt. Das hilft imo sehr, tieferes Verständnis für die Materie zu entwickeln 🙂



  • Danke für die antworten.
    So aber was ist denn jetzt genau an meinem Code falsch??

    -GhostfaceChilla-



  • In Zeile 17 forderst du zu wenig Speicher an.

    In Zeile 17 (und 32) behandelts du dyn_array richtig. in Zeile 18, 20 und 21 schon nicht mehr.

    dyn_array ist eine Liste, die auf die Strings verweist.
    Du kannst nicht mit einem Vergleich schauen ob das Wort schon eingegeben wurde. Du musst das schon mit allen Einträgen vergleichen.
    (Ja, in einer Schleife, jeden Eintrag einzeln.)



  • @Wutz:
    Was bringt dir in deinem Quellcode folgendes.

    while( w-- )
    

    ??
    Das kann ja gar keine while-Schleife sein oder?Hier wird ja keine Bedingung überprüft.

    -GhostfaceChilla-



  • Natürlich wird hier eine Bedingung geprüft. Was hier steht, ist dasselbe wie while(w-- != 0).
    Du kannst statt if(x != 0), while(x != 0),... auch if(x), while(x),... schreiben 😉



  • Habs eben gegoogelt und hab herausgefunden wie es funktioniert 🙂
    D.h also es überprüft solange bis w= 0 ist stimmts?

    -GhostfaceChilla-



  • Wenn w == 0 ist, bricht die Schleife sofort ab und nichts passiert, ansonsten wird heruntergezählt bis 0 und der Schleifenblock jeweils mit w-1 bedient.


Anmelden zum Antworten