Problem mit malloc();



  • Hallo,
    also ich schreibe in C ein Programm, welches alle Wörter in einem Text erkennen soll, und mir als Mehrdimensionales Array zurückgeben soll.

    Hier mein bisheriges:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    #define BUFFER 255
    
    void getword(char **words,char *text) {   
       char *p = text;
       char buffer[BUFFER+1];   
       int i=0,j=0;
    
       while(*p!='\0') {
          i = 0;
          memset(buffer,0,sizeof(buffer));
    
          for(;*p != '\0' && i<BUFFER;*++p) {
             if(isspace(*p)) { //Wenn Whitespace, Wort zuende
                *++p;        
                break;
             }
    
          if(isalnum(*p)) //Satzzeichen ignorieren    
             buffer[i++] = *p;           
          }
    
          /************************************
             Platz fuer Wort reservieren    
          **************************************/
    
          words = (char **)realloc(words,sizeof(char *));
          words[j] = (char *)malloc(strlen(buffer)+1);        
          memset(words[j],0,sizeof(words[j]));
    
          //Buffer nach words[j] kopieren
          strcpy(words[j],buffer);
          j++;  
       }
    
       //Zum Schluss NULL Hinzufügen
       words = (char **)realloc(words,sizeof(char *));
       words[j] = (char *)malloc(sizeof(NULL));
       words[j] = NULL;       
    }
    
    int main(void) {
       char *text = "Dies ist ein Beispieltext, um zu testen, ob mein Script wirklich funktioniert. Deswegen kommen jetzt ein paar Fuellwoerter wie zum Beispiel, Hallo Welt, Moin Moin, Wie geht es dir, und so weiter. Ich hoffe ihnen gefaellt mein Beispiel. Denn dieser Script ist echt genial einfach und effektiv.";
       char **words = (char **)malloc(sizeof(char *));
       int i;
    
       getword(words,text);
    
       //Wörter ausgeben   
       for(i=0;words[i]!= NULL;i++) {
          printf("%s\n",words[i]); 
       }
       return 0;
    }
    

    Also die Ausgabe sieht erstmal richtig aus, allerdings fängt diese so an:

    ð9=
    ►:=
    P:=
    ÿ:=

    @;=
    testen

    Wenn ich jetzt die Wörter (buffer, bzw. words[j]) innerhalb der Funktion ausgeben, funktioniert dies anstandslos.
    Deswegen gehe ich davon aus, dass diese irgendwie Überschrieben werden.

    Kann mir jmd. helfen?



  • die Größe des "realloc()"ierten Bereiches stimmt nicht - du reservierst nur Platz für einen char*. Richtig müßte das heißen:

    words=(char**)realloc(words,(j+1)*sizeof(char*));
    

    und für den NULL-Pointer brauchst du auch keinen Speicherplatz anlegen.



  • der <words> zeiger in main() wird nicht geaendert, wenn du realloc()st.

    probier mal
    getword(char ***words,...
    ...
    getword(&words,text);



  • Hallo,
    @CStoll: Das habe ich mir schon gedacht. Aber wenn ich es wie gesagt ändere, erhalte ich jetzt eine Fehlermeldung beim Aufruf:

    Dev-C++ sagt: Eine Zugriffverletzung (Segmentation Fault) trat in ihrem Programm auf.

    @c.rackwitz: Hab alles durchprobiert. Dabei erhalte ich aber immer ein Warning und das Programm stürtzt ab.



  • dieter, dein code ist broken.

    schau dir mal an, was realloc() macht und wie du den <words> pointer aendern kannst.



  • Hallo,
    @c.rackwitz: Also realloc(); vergrößert die Blockgröße auf den Wert von size und gibt bei Erfolg die Adresse des geänderten Speicherblocks zurück.

    Dass meine erste Variante nicht ganz richtig ist, da sich ja die größe nicht ändert, ist mir auch bewusst.

    Aber auch wenn ich dort eine Variable wie im Beispiel von CStoll einbaue, funktionert es leider gar nicht mehr.



  • an deiner stelle wuerd ich nicht versuchen, den code zu fixen sondern ihn komplett neu schreiben.
    und das schritt fuer schritt, damit du sofort siehst, wo fehler reinkommen.
    fangen wir mal einfach an:

    void getwords(char *test, char ***pwords) {
    
    // hier kommt der algorithmus hin
    
    }
    
    int main(void) {
       char *text = "Dies ist ein Beispieltext, um zu testen, ob mein Script wirklich funktioniert. Deswegen kommen jetzt ein paar Fuellwoerter wie zum Beispiel, Hallo Welt, Moin Moin, Wie geht es dir, und so weiter. Ich hoffe ihnen gefaellt mein Beispiel. Denn dieser Script ist echt genial einfach und effektiv.";
       char **words;
       int i;
    
       words = malloc(sizeof(char*));
       words[0] = 0;
    
       getwords(text, &words); // &words, weil der pointer veraendert wird
    
       //Wörter ausgeben  
       for(i = 0; words[i]; i++) {
          printf("%s\n",words[i]);
       }
    
       // das raeumt hinterher wieder auf
       if (words) {
          for (i = 0; words[i]; ++i)
             free(words[i]);
          free(words);
       }
       return 0;
    }
    

    nimm diesen code bitte als basis und verstehe ihn soweit (der aufraeumabschnitt und wieso wir einen char*** brauchen).

    im naechsten schritt fangen wir mit getwords() an.



  • Hallo,
    so hab mal etwas gebastelt, und folgendes ist rausgekommen.
    Bei dem Text geht es:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    #define BUFFER 255
    
    struct tnode {
       char *word;
       int count;
       struct tnode *left;
       struct tnode *right;
    };
    
    char **getword(char *text) {  
       char *p = text;
       char buffer[BUFFER+1];  
       int i=0,j=0;
    
       char **words = NULL;
    
       while(*p!='\0') {
          i = 0;
          memset(buffer,0,sizeof(buffer));
    
          for(;*p != '\0' && i<BUFFER;*++p) {
             if(isspace(*p)) { //Wenn Whitespace, Wort zuende
                *++p;        
                break;
             }
    
          if(isalnum(*p)) //Satzzeichen ignorieren    
             buffer[i++] = *p;                 
          }
    
          /************************************
             Platz fuer Wort reservieren    
          **************************************/
    
          words = realloc(words,(j+1)*sizeof(char *));         
          words[j] = (char *)malloc(strlen(buffer)+1);  
    
          memset(words[j],0,sizeof(words[j]));
    
          //Buffer nach words[j] kopieren
          strcpy(words[j],buffer); 
    
          j++;  
       }
    
       return words;    
    }
    
    int main(void) {
       char *text = "Dies ist ein Beispieltext, um zu testen, ob mein Script wirklich funktioniert. Deswegen kommen jetzt ein paar Fuellwoerter wie zum Beispiel, Hallo Welt, Moin Moin, Wie geht es dir, und so weiter. Ich hoffe ihnen gefaellt mein Beispiel. Denn dieser Script ist echt genial einfach und effektiv.";
       char **words = NULL;
       int i;
    
       words = getword(text);
    
       //Wörter ausgeben  
       for(i=0;words[i]!= NULL;i++) {
          printf("%s\n",words[i]);
       }
    
       //Mit free den Bereich wieder freigeben
    
       return 0;
    }
    


  • schnell druebergeguckt:

    memset(words[j],0,sizeof(words[j]));
    

    ist falsch. sizeof() eines pointers ist auf 32bit systemen immer 4.



  • Falls der memset darauf abzielte den gesamten String zu nullen, sei noch angemerkt wenn direkt darauf ein strcpy folgt, ist das garnicht nötig. Wenn man nur den String mit "" initialisieren möchte reicht es das erste Zeichen zu nullen.


Anmelden zum Antworten