Array in einer For-Schleife Werte aus Datei zuweisen. Werte zuerst richtig, dann falsch.



  • Hallo!
    Ich möchte aus einer Datei Werte einlesen und in structs speichern, die wiederum in einem Array liegen.

    Das öffnen der Datei und das Einlesen der einzelnen Zeilen funktioniert.
    Genauso wie das Erkennen der Semikolons in den Zeilen.

    Wenn ich jedoch versuche jeder Person (0 bis 3) in einer for-Schleife die Werte aus der Datei zuzuweisen, funktioniert dies erst, danach erhält aber jede Person die selben Daten, und zwar die aus der letzten Zeile meiner Datei.

    Hier mein Quellcode:

    #include <stdio.h>
    #define LAENGE 10 //länger der einzelnen Zeilen
    #define ANZAHL 4 //Anzahl der Zeilen
    
    struct person {
    char *name ;
    int *alter;
    char *ort ; 
    };
    
    int main (void)
    {
    
    struct person personen[4];
    
    FILE *datei; // Datei Inhalt: Pro Zeile drei Werte, jeweils mit Semikolon getrennt. name;alter;ort
    char line[ANZAHL][LAENGE];
    int i ;
    char delimiter[] = ",;";
    char *ptr;
    datei = fopen ("test.txt", "r");
    	if (datei != NULL)
    	{
    		for(i = 0; i < ANZAHL;i++) {
    		fgets(line,LAENGE,datei); 
    
    		ptr = strtok(line, delimiter);  	// initialisieren und ersten Abschnitt erstellen
    
    			personen[i].name=ptr;     
    			ptr = strtok(NULL, delimiter);
    			personen[i].alter=ptr;
     			ptr = strtok(NULL, delimiter);
     			personen[i].ort=ptr;
     			ptr = strtok(NULL, delimiter);
    
     			printf("\nPerson %i ist jetzt gerade %s und %s\n ",i,personen[i].name,personen[i].alter); //Ausgabe korrekt
    			printf("Person 1: Name: %s\n Alter: %s\n Ort: %s",personen[0].name,personen[0].alter, personen[0].ort); //Ausgabe nicht korrekt. Gespeichert sind die Werte der letzten Person (letzter For-Schleifen Durchlauf)
    
    		}	
    
    	close (datei);
    	}
    
    system("Pause");
    return 0;
    }
    

    PS: Bin noch nicht so lange dabei, also kann gut sein, dass ich ziemlich viel Mist gebaut habe. Ich hoffe, Ihr könnt mir trotzdem weiter helfen 🙂

    Danke !


  • Mod

    Mit = kopiert man keine Zeichenketten, sondern bloß die Zeiger da drauf. Da der kopierte Zeiger in diesem Fall immer auf dein Eingabearray zeigt, wird entsprechend auf die letzte Eingabe verwiesen. strcpy kopiert Zeichenketten, aber du brauchst natürlich irgendwo echten Speicher, nicht bloß Zeiger.



  • Warum hast du line als 2D-Array angelegt?
    Warum nutzt du es nicht?
    (Allerdings ist das auch nicht der ideale Weg, aber du hast dir sicher etwas dabei gedacht)

    Reichen 9 Zeichen pro Zeile wirklich aus?
    Da bleibt nicht viel Platz für Name;Alter;Ort

    Dein Compiler (muss) Warnungen ausgeben. (Inkompatibler Zeiger beit fgets und unbekanntes strtok )
    Behandele diese wie Fehler und beseitige deren Ursache.
    Stelle den Warnlevel so ein, dass der Compiler möglichst viele Warnungen ausgibt.



  • - benutze C-Codetags
    - wieso benutzt du in Zeile 16 nicht ANZAHL?
    - close ist hier falsch (Z.47)
    - nur Deppen benutzen system("pause")
    - wieso ist delimiter ",;", wenn nur Semikolon vorkommt?
    - du prüfst fgets nicht

    Entscheidend sind Zeile 27+30, du legst ein Stringarray an, verwendest aber nur das erste Element, das wird immer wieder überschrieben.

    #define LAENGE 100 //länger der einzelnen Zeilen
    #define ANZAHL 4 //Anzahl der Zeilen
    
    struct person {
      char *name;
      int *alter;
      char *ort;
    };
    
    int main(void)
    {
    
      struct person personen[ANZAHL];
    
      FILE *datei; // Datei Inhalt: Pro Zeile drei Werte, jeweils mit Semikolon getrennt. name;alter;ort
      char line[ANZAHL][LAENGE];
      int i;
      char delimiter[] = ",;";
      char *ptr;
      datei = fopen("test.txt", "r");
      if (datei != NULL)
      {
        for (i = 0; i < ANZAHL; i++) {
          fgets(line[i], LAENGE, datei);
    
          ptr = strtok(line[i], delimiter);      // initialisieren und ersten Abschnitt erstellen
    
          personen[i].name = ptr;
          ptr = strtok(NULL, delimiter);
          personen[i].alter = ptr;
          ptr = strtok(NULL, delimiter);
          personen[i].ort = ptr;
          ptr = strtok(NULL, delimiter);
    
          printf("\nPerson %i ist jetzt gerade %s und %d\n ", i, personen[i].name, personen[i].alter ? atoi(personen[i].alter) : 0); //Ausgabe korrekt
          printf("Person 1: Name: %s\n Alter: %d\n Ort: %s", personen[i].name, personen[i].alter ? atoi(personen[i].alter) : 0, personen[0].ort); //Ausgabe nicht korrekt. Gespeichert sind die Werte der letzten Person (letzter For-Schleifen Durchlauf)
    
        }
    
        fclose(datei);
      }
    
      return 0;
    }
    

    Aber nun mal im Ernst, sowas wie oben macht niemand, und nur Deppen sehen es als Lösung an, weil es ja "funktioniert";

    die allgemeine Lösung für deinen Fall ist fgets+sscanf: (pseudo)

    i = 0
    while( fgets(tempzeile) )
      if( OK==sscanf(...,tempstructvar) )
      {
        i++
        realloc_structmem i
        structmem[i-1] = tempstructvar
      }
    

    Das funktioniert immer, da es auf konstante Arrays verzichtet.



  • Super, vielen Dank für die schnellen Antworten!
    Ihr habt mir echt geholfen 🙂

    Jaa ich weiß, das ist alles nicht besonders elegant, was ich da fabriziert hab..

    und @Wutz: Ich bin vielleicht n kleines doofes Blondchen, was gerade mit Programmieren angefangen hat, aber sicherlich kein Depp! Frechheit 😃


Anmelden zum Antworten