Verständnisproblem char array



  • Hallo zusammen,

    ich bin neu hier und beschäftige mich gerade mit Ansi-C

    Hierbei habe ich ein Verständnisproblem.

    Ich möchte eine Textdatei einlesen, die z.B. so aussieht:

    Test1;Test2;Test3;Test4;Test5
    Test101;Test202;Test303;Test404;Test505

    usw.

    Ich habe bereits einige Examples im Internet durchgelesen und probiert
    und mehrfach selbst einiges geschrieben, aber ich denke ich habe es bisher
    einfach nicht kapiert.

    Das ganze soll Zeilenweise in Arrays eingelesen werden.

    z.B.
    Zeile1:
    myarray[0][0]=Test1;
    myarray[0][1]=Test2;
    myarray[0][2]=Test3;
    myarray[0][3]=Test4;
    myarray[0][4]=Test5;
    Zeile2:
    myarray[1][0]=Test101;
    myarray[1][1]=Test202;

    usw...

    Kann mir jemand evtl. ein Tutorial oder ein Beispiel liefern wie
    ich die Ascii-Datei einlesen muss, damit ich die einzelnen Strings in
    in das Array schreiben kann?

    Vielen Dank.



  • #define MAX_L 100
    #define MAX_V 100
    
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char myarray[MAX_L][MAX_V];
        FILE *datei = fopen("dateiname", "r");
        char inhalt[1024];
        int counter = 0;
        int counter2 = 0;
        char *ptr;
    
        while(fgets(inhalt, sizeof inhalt, datei) != NULL)
        {
            ptr = strtok(inhalt, ";");
            myarray[counter][0] = ptr;
            while(ptr != NULL)
            {
                ptr = strtok(NULL, ";");
                counter2++;
                myarray[counter][counter2] = ptr;
            }
            counter++;
        }
    
        fclose(datei);
        return 0;
    }
    


  • Vielen Dank! 🙂

    Dann lag ich gar nicht so verkehrt wie ich dachte.
    Dann liegt mein Problem wohl eher auf das spätere Zugreifen des Array.
    Ich habe unten einfach mal zum testen ein "printf" eingefügt.
    Hier bekomme ich allerdings keine Ausgabe.

    #define MAX_L 100
    #define MAX_V 100
    
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char myarray[MAX_L][MAX_V];
        FILE *datei = fopen("dateiname", "r");
        char inhalt[1024];
        int counter = 0;
        int counter2 = 0;
        char *ptr;
    
        while(fgets(inhalt, sizeof inhalt, datei) != NULL)
        {
            ptr = strtok(inhalt, ";");
            myarray[counter][0] = ptr;
            while(ptr != NULL)
            {
                ptr = strtok(NULL, ";");
                counter2++;
                myarray[counter][counter2] = ptr;
            }
            counter++;
        }
    
        fclose(datei);
        printf("s: %s\n",myarray[0][1]);
        return 0;
    }
    


  • Das funktioniert aber nur mit einer Zeile 🙂
    Außerdem sollte counter2 in der Schleife mal auf 0 gesetzt werden.

    Mach auch mal

    printf("s: %s\n",myarray[0][0]);
    

    und hinter der Zeile mit strtok ein

    printf("p: <%s>\n",ptr);
    


  • Da funktioniert überhaupt nichts, da in

    myarray[counter][0] = ptr;
    

    und auch woanders myarray[x][y] als char* behandelt wird, jedoch ein simples char ist. Ich würde dir nicht empfehlen, mit diesem Schrott weiterzumachen oder gar irgendwo abzuliefern.



  • Ich habe da mal was vorbereitet:

    int splitteProZeile(const char *name,char ****m,char t)
    { /* gibt die Anzahl der gelesenen und ausgewerteten Zeilen zurück */
      int r=0;
      size_t len = 999;
      char c=0,*buffer=calloc(1,len);
      FILE *f = fopen(name,"rt");
      if( !f ) return r;
      setvbuf(f,0,_IOLBF,4096);
      do
        if( c=='\n'||feof(f) )
        {
          size_t i=1;
          char *p=buffer;
          if(c!=EOF||*p) {
          *m=realloc(*m,++r*sizeof*m);
          (*m)[r-1]=calloc(1,sizeof*m);
          while( strchr(p,t) )
           (*m)[r-1]=realloc((*m)[r-1],++i*sizeof*m),memmove(&(*m)[r-1][i-1],&(*m)[r-1][i-2],sizeof*m),strncat((*m)[r-1][i-2]=calloc(1,strchr(p,t)-p+1),p,strchr(p,t)-p),p=strchr(p,t)+1;
          (*m)[r-1]=realloc((*m)[r-1],++i*sizeof*m),memmove(&(*m)[r-1][i-1],&(*m)[r-1][i-2],sizeof*m),strncat((*m)[r-1][i-2]=calloc(1,strlen(p)+1),p,strlen(p));
          *buffer=0;}
          if( feof(f) ) {free(buffer);break;}
        }
        else
        if( !feof(f) )
        {
          if( strlen(buffer)==len-1 )
            buffer=realloc(buffer,++len);
          strncat(buffer,&c,1);
        }
      while( c=fgetc(f),1 );
      fclose(f);
      return r;
    }
    
    int main()
    {
      char ***m=0,***o;
      int r=splitteProZeile("deine Textdatei",&m,';');
      o=m;
      if(o)
      {
        while( r-- )
        {
          char **z=*o;
          while( *z )
            printf("%s ",*z),free(*z++);
          puts("");
          free(*o++);
        }
        free(m);
      }
      return 0;
    }
    

    Das Beispiel kommt ohne Annahmen über vorhandene Zeilenanzahl, Zeilenlängen und Werteanzahl pro Zeile in der Textdatei aus, wertet Leerfelder ("a;;b") richtig aus (im Gegensatz zu strtok) und zeigt in main ein Beispiel zum Durchlauf des Ergebnis und der Freigabe des in splitteProZeile belegten dynamischen Speichers.
    Wenn du char**** verstanden hast, kannst du beruhigt in jede C Klausur gehen.



  • Das is der hässlichste Code, den ich seit langem gesehen hab. C-Frickelcode in Reinform.



  • Wutz schrieb:

    Ich habe da mal was vorbereitet:
    Das Beispiel kommt ohne Annahmen über vorhandene Zeilenanzahl, Zeilenlängen und Werteanzahl pro Zeile in der Textdatei aus, wertet Leerfelder ("a;;b") richtig aus (im Gegensatz zu strtok) und zeigt in main ein Beispiel zum Durchlauf des Ergebnis und der Freigabe des in splitteProZeile belegten dynamischen Speichers.
    Wenn du char**** verstanden hast, kannst du beruhigt in jede C Klausur gehen.

    Super, vielen Dank! 🙂

    Das muss ich mir jetzt mal in Ruhe anschauen und verstehen.
    Ich arbeite mich zwar bereits durch C Bücher für Anfänger,
    aber so weit führen diese leider nicht.

    Kann jemand weitere C-Bücher für Anfänger und für später etwas fortgeschrittener empfehlen?



  • Grauenhaft2 schrieb:

    Das is der hässlichste Code, den ich seit langem gesehen hab. C-Frickelcode in Reinform.

    😃

    Besonders das o=m in main will sich mir, auch nach mehrmaligen hinsehen, nicht erschließen. Den Rest versuche ich erst gar nicht nachzuvollziehen. Also Zeile 18 und 19 sind ja wohl der reinste Horror. Und da sage noch mal jemand Makros wären böse. In genau solchen Fällen sind sie sehr nützlich und alles andere als böse, sie machen aus deinem Code eher was, was auch ein Anfänger verstehen kann. Und so einer scheint mir auch der Fragesteller zu sein.

    Okay dass mit dem o=m ist klar, weil du o veränderst und dann free auf m machst. Aber deswegen soll man auch aussagekräftige Namen nutzen und den Code dokumentieren. Mit sowas kann doch selbst ein Profi nichts anfangen und wirfst das einem Anfänger vor. Und dass du das mal eben zusammen geschustert hast, glaube ich dir auch nicht. Da muss man schon extrem konzentriert bei der Sache sein, um da keine Bugs zu provozieren. Falls das aber dein Ernst sein soll, dann hast du meinen Respekt. Gäbe es mehr von deiner Sorte, oder wären alle so gut, dann wären Bugs in der Softwarewelt kein Thema mehr.



  • Wutz schrieb:

    Ich habe da mal was vorbereitet:

    Wenn ich das Ganze mit gcc (gcc -Wall test2.c -o test2 -lauto) compilieren will, erhalte folgende errors:

    test2.c: In function splitteProZeile': test2.c:4: error:size_t' undeclared (first use in this function)
    test2.c:4: error: (Each undeclared identifier is reported only once
    test2.c:4: error: for each function it appears in.)
    test2.c:4: error: parse error before "len"
    test2.c:5: warning: implicit declaration of function calloc' test2.c:5: error:len' undeclared (first use in this function)
    test2.c:5: warning: initialization makes pointer from integer without a cast
    test2.c:6: error: FILE' undeclared (first use in this function) test2.c:6: error:f' undeclared (first use in this function)
    test2.c:6: warning: implicit declaration of function fopen' test2.c:8: warning: implicit declaration of functionsetvbuf'
    test2.c:8: error: _IOLBF' undeclared (first use in this function) test2.c:10: warning: implicit declaration of functionfeof'
    test2.c:12: error: parse error before "i"
    test2.c:14: error: EOF' undeclared (first use in this function) test2.c:15: warning: implicit declaration of functionrealloc'
    test2.c:15: warning: assignment makes pointer from integer without a cast
    test2.c:16: warning: assignment makes pointer from integer without a cast
    test2.c:17: warning: implicit declaration of function strchr' test2.c:18: error:i' undeclared (first use in this function)
    test2.c:18: warning: assignment makes pointer from integer without a cast
    test2.c:18: warning: implicit declaration of function memmove' test2.c:18: warning: implicit declaration of functionstrncat'
    test2.c:19: warning: assignment makes pointer from integer without a cast
    test2.c:19: warning: implicit declaration of function strlen' test2.c:21: warning: implicit declaration of functionfree'
    test2.c:27: warning: assignment makes pointer from integer without a cast
    test2.c:30: warning: implicit declaration of function fgetc' test2.c:31: warning: implicit declaration of functionfclose'
    test2.c: In function main': test2.c:46: warning: implicit declaration of functionprintf'
    test2.c:47: warning: implicit declaration of function `puts'

    Mal schauen ob ich das selbstständig hinbekomme.



  • Schon mal an #include <die_üblichen_Verdächtigen> gedacht?



  • Da gehts doch schon los, wobei ich das Problem jetzt nicht unbedingt Wutz ankreiden würde.
    Um die entsprechenden Header zu ermitteln, kann man auf der Kommandozeile in Linux einfach "man <Funktionsname>" eingeben. Ohne die spitzen Klammern. Alternativ in die Suchmaschine deiner Wahl. So lässt sich das am einfachsten Auflösen.



  • DirkB schrieb:

    Schon mal an #include <die_üblichen_Verdächtigen> gedacht?

    Oh man, bin ich blöd!!
    Ja, die hab ich total übersehen in meiner Euphorie!

    Danke für den Hinweis.



  • Nick Unbekannt schrieb:

    Da gehts doch schon los, wobei ich das Problem jetzt nicht unbedingt Wutz ankreiden würde.
    Um die entsprechenden Header zu ermitteln, kann man auf der Kommandozeile in Linux einfach "man <Funktionsname>" eingeben. Ohne die spitzen Klammern. Alternativ in die Suchmaschine deiner Wahl. So lässt sich das am einfachsten Auflösen.

    War, wie gesagt, meine eigene Blödheit.
    Das mit den includes ist natürlich klar.
    Hab mir gerade echt an den Kopf gefasst, als ich den Hinweis laß.
    Es fiel mir wie Schuppen von den Augen.


Log in to reply