einfach verkettete Liste aus einer Textdatei laden
-
Hallo,
schreibe eine verkettete Liste. Diese soll in eine textdatei gespeichert werden und wieder geladen werden können. Das speichern funtkioniert auch. Nur das Laden nicht.In der Textdatei steht dann folgendes:
12345, Name, 1, 12[Erläuterung zur Textdatei:
12345(Artikelnummer, Typ long int), Name (Artikelbezeichenung, Typ char[]), 1 (Preis, Typ float), 12 (Anzahl, Typ long int)]Nach Programmabsturz hab debugt und festgestellt, dass die einzelnen Elemente nicht richtig zugeordnet werden. Hab auch schon im Internet gesucht und einiges gelesen, aber noch nicht richtig verstanden, was genau ich machen muss. Vielleicht kann mir jemand erklären, wie ich meinen Code verändern muss, damit es funktioniert.
void laden () { FILE *f; char file_name[255]; struct daten * lager_ptr, lager_daten; printf("Welchen Datensatz wollen Sie laden: "); scanf("%s", file_name); fflush(stdin); f = fopen(file_name, "r"); if(f ==NULL) { printf("Fehler beim Oeffnen von %s\n", file_name); return; } while (fread(&lager_daten, sizeof(struct daten), 1, f)) { if (head==NULL) { head = (struct daten *) malloc(sizeof(struct daten)); if (head == NULL) { printf("Speicherplatzmangel!!!!\n"); exit (0); } else { head->artikelnr = lager_daten.artikelnr; strcpy(head ->name, lager_daten.name); head->anzahl=lager_daten.anzahl; head->preis = lager_daten.preis; head->next = NULL; } } else { lager_ptr = head; while(lager_ptr->next != NULL) lager_ptr = lager_ptr->next; lager_ptr->next = (struct daten *) malloc(sizeof(struct daten)); if(lager_ptr->next ==NULL) { printf("Speicherplatzmangel!!!\n"); exit(0); } else { lager_ptr = lager_ptr->next; lager_ptr -> artikelnr=lager_daten.artikelnr; strcpy(lager_ptr->name, lager_daten.name); lager_ptr->anzahl=lager_daten.anzahl; lager_ptr->preis = lager_daten.preis; lager_ptr->next = NULL; } } } printf("Datensatz geladen\n"); fclose(f); }
Für eure Hilfe bin ich wirklich dankbar
-
Hallo,
an welcher Stelle im Code gibt es den Absturz?
-
Das Programm stürzt beim Zuordnen der einzelnen Werte ab. Die Artikelnummer wird nicht ganz "geladen" und der ganze Rest wird in die Variable für die Bezeichnung "geladen". So wie ich das beurteile (und beim debuggen gesehen habe), muss der Fehler in der letzten else - Anweisung liegen. Ganz sicher bin ich mir da aber nicht, da stimmen die Zuweisungen nicht mehr richtig.
-
Ist head mit NULL initialisiert? Haben deine Strukturvariable den richtigen Datentypen (char* wäre schonmal nicht richtig)?
Btw. brauchst du dich nicht immer wieder vom Beginn der Liste bis zum Ende zu hangeln, wenn es dazu keinen triftigen Grund gibt. Es genügt, das neue Element einfach anzuhängen.
-
ja, head ist mit NULL initialisiert. Wenn ich so weit wäre, dass zumindest ein in der Datei stehendes Element richtig eingelesen wird, würde ich mir auch Gedanken darüber machen, dass ich jedesmal von vorne Anfange. Aber dafür muss ja ersteinmal überhaupt etwas richtig zugeordnet werden, sonst ist es auch egal, dass ich immer wieder am Anfang beginne.
Vielleicht hast mal ein Code - Beispiel für mich?!?
-
Krümel1411 schrieb:
ja, head ist mit NULL initialisiert.
Und wie sehen deine Strukturvariable aus? Wie hast du die Daten in die Datei geschrieben?
Vllt. probierst du erstmal hartkodierte Werte zum Testen?
-
Das sind meine Strukturvariablen:
struct daten { long int artikelnr; char name[21]; float preis; long int anzahl; struct daten *next; //Zeiger der Struktur };
Werde es mal versuchen, obwohl irgendwie das Gefühl habe, dass ich damit nicht viel weiter komme
Aber werde es versuchen und mich dann nochmal melden.
-
Das sieht alles ganz gut aus. Was passiert, wenn du dir die mit fread eingelesenen Werte vor der Zuweisung anzeigen lässt ( Debugger oder printf )?
-
while (fread(&lager_daten, sizeof(struct daten), 1, f)) // <- ! ... lager_ptr -> artikelnr=lager_daten.artikelnr; strcpy(lager_ptr->name, lager_daten.name); lager_ptr->anzahl=lager_daten.anzahl; ...
Ist "12345, Name, 1, 12" genauso lang wie sizeof(struct daten)? Was soll daten mit dem Komma machen?
Stichwort: Tempbuffer, parsen.
-
Sind die char Arrays terminiert?
-
Stimmt, das ich das nicht gleich gesehen habe.
Du hast eine Textdatei, in der die Werte duch Kommas getrennt sind und liest daraus in einer Schleife Häppchen der Größe sizeof(struct daten) ein.
Das ist nicht das richtige Konzept.
Wenn also jede Zeile deiner Textdatei einen Datensatz repräsentieren soll, bietet es sich an, zeilenweise einzulesen und die Werte zu extrahieren.Die einfachere Variante ist mit fwrite/fread machbar, aber die Textdatei ist dann kaum lesbar.
-
Mahlzeit,
habe auch ein Problem mit dem laden meiner Liste.
Ich kann zwar laden, jedoch lädt er nur mein ersten "Artikel" aus meiner Struktur von insgesamt dreien, die ich abgespeichert habe.FILE *fp; fp = fopen( "Lagerverwaltung.txt", "r"); while(fread(&lager_daten, sizeof(struct lagerverwaltung),1,fp)) { if(head == NULL) { head = (struct lagerverwaltung *)malloc(sizeof(struct lagerverwaltung)); if(head == NULL) { printf("Speichermangel!!\n"); exit(0); } else { head->Artikelnummer = lager_daten.Artikelnummer; strcpy(head->Bezeichnung, lager_daten.Bezeichnung); head->Preis = lager_daten.Preis; head->Anzahl = lager_daten.Anzahl; head->next = NULL; } } else { lager_ptr = head; while(lager_ptr->next != NULL) lager_ptr = lager_ptr->next; lager_ptr->Artikelnummer = lager_daten.Artikelnummer; strcpy(lager_ptr->Bezeichnung, lager_daten.Bezeichnung); lager_ptr->Preis = lager_daten.Preis; lager_ptr->Anzahl = lager_daten.Anzahl; lager_ptr->next = NULL; }
Hoffe ihr jemand kann mir helfen, würde mich freuen.
Bis dann
-
So wie ich das überblicke ist am Anfang dein head gleich 0, du überschreibst head mit neuen Werten, dann für die zweite Struktur ist head ungleich 0 weil es gerade überschrieben wurde und wird wieder überschrieben. Damit speicherst du die erste Struktur, dann speicherst du die zweite über die erste, dann die dritte drüber.
Zwischen Zeile 28 und 29 sollte sowas wie lager_ptr->next = malloc(sizeof *lager_ptr->next); stehen und du musst alles in lager_ptr->next speichern, nicht in lager_ptr.
-
nwp2 schrieb:
So wie ich das überblicke ist am Anfang dein head gleich 0, du überschreibst head mit neuen Werten, dann für die zweite Struktur ist head ungleich 0 weil es gerade überschrieben wurde und wird wieder überschrieben. Damit speicherst du die erste Struktur, dann speicherst du die zweite über die erste, dann die dritte drüber.
Zwischen Zeile 28 und 29 sollte sowas wie lager_ptr->next = malloc(sizeof *lager_ptr->next); stehen und du musst alles in lager_ptr->next speichern, nicht in lager_ptr.Hmm... Er gibt mir eine Fehlermeldung, wenn ich
lager_ptr->next = malloc(sizeof *lager_ptr->next);
an die von dir genannte stelle eingebe.
Fehlermeldung:
error C2440: '=': 'void *' kann nicht in 'lagerverwaltung *' konvertiert werden
Was meinst du eigentlich mit dem
alles in lager_ptr->next speichern, nicht in lager_ptr
?
Ich habe mal meine komplette Speicher/Lade-Funktion beigefügt vielleicht hilft das hja weiter:
void SpeichernLaden() { char auswahl; char dateiname[20]; struct lagerverwaltung *lager_ptr, lager_daten; system("cls"); printf("Waehlen Sie aus: \n"); printf("<S>peichern\n"); printf("<L>aden\n\n"); printf("<B>eenden\n\n"); do { scanf("%c", &auswahl); if(auswahl == 'S' || auswahl == 's') { printf("\nGeben Sie einen Dateinamen ein (z.B.: Test.txt): "); scanf("%s", dateiname); FILE *fp; fp = fopen(dateiname, "wb"); lager_ptr = head; if(lager_ptr == NULL) { printf("\nListe ist leer!\n\n"); return; } while(lager_ptr != NULL) { fwrite(lager_ptr, sizeof(struct lagerverwaltung),1,fp); lager_ptr = lager_ptr->next; } fclose(fp); printf("\nSpeichern erfolgreich abgeschlossen!\n\n\n"); _getch(); system("cls"); break; } if(auswahl == 'L' || auswahl == 'l') { FILE *fp; fp = fopen( "Lagerverwaltung.txt", "r"); while(fread(&lager_daten, sizeof(struct lagerverwaltung),1,fp)) { if(head == NULL) { head = (struct lagerverwaltung *)malloc(sizeof(struct lagerverwaltung)); if(head == NULL) { printf("Speichermangel!!\n"); exit(0); } else { head->Artikelnummer = lager_daten.Artikelnummer; strcpy(head->Bezeichnung, lager_daten.Bezeichnung); head->Preis = lager_daten.Preis; head->Anzahl = lager_daten.Anzahl; head->next = NULL; } } else { lager_ptr = head; while(lager_ptr->next != NULL) lager_ptr = lager_ptr->next; lager_ptr->next = malloc(sizeof *lager_ptr->next); lager_ptr->Artikelnummer = lager_daten.Artikelnummer; strcpy(lager_ptr->Bezeichnung, lager_daten.Bezeichnung); lager_ptr->Preis = lager_daten.Preis; lager_ptr->Anzahl = lager_daten.Anzahl; lager_ptr->next = NULL; } } fclose(fp); system("cls"); break; } if(auswahl == 'B' || auswahl == 'b') break; }while(1); }
-
FreshAC schrieb:
Hmm... Er gibt mir eine Fehlermeldung, wenn ich
lager_ptr->next = malloc(sizeof *lager_ptr->next);
an die von dir genannte stelle eingebe.
Das liegt daran dass du einen C++-Compiler und keinen C-Compiler verwendest. Unter C++ musst du malloc casten, also lager_ptr->next = (struct lagerverwaltung *)malloc(sizeof *lager_ptr->next);
FreshAC schrieb:
Was meinst du eigentlich mit dem
alles in lager_ptr->next speichern, nicht in lager_ptr
?
Du hast deinen lager pointer, dort speicherst du deine Struktur. Die nächste Struktur musst du dann in lager_ptr->next speichern, die nächste dann in lager_ptr->next->next. Wenn du bis zur letzten Struktur wanderst musst du die nächste dann in lager_ptr->next speichern. Wenn du es in lager_ptr speicherst überschreibst du deine letzte Struktur.
-
FreshAC schrieb:
error C2440: '=': 'void *' kann nicht in 'lagerverwaltung *' konvertiert werden
du verwendest nen c++ compieler? versuch mal .c als datei endung
findest du
malloc(sizeof(struct lagerverwaltung)) nicht auch viel schöner als malloc(sizeof *lager_ptr->next)
??
wenn du den ersten fehler nichtmehr bekommst kannst es auch sein lassen den rückgabewert von malloc zu casten
-
Das liegt daran dass du einen C++-Compiler und keinen C-Compiler verwendest. Unter C++ musst du malloc casten, also lager_ptr->next = (struct lagerverwaltung *)malloc(sizeof *lager_ptr->next);
Also der Fehler wird nicht mehr angezeigt.
Du hast deinen lager pointer, dort speicherst du deine Struktur. Die nächste Struktur musst du dann in lager_ptr->next speichern, die nächste dann in lager_ptr->next->next. Wenn du bis zur letzten Struktur wanderst musst du die nächste dann in lager_ptr->next speichern. Wenn du es in lager_ptr speicherst überschreibst du deine letzte Struktur.
Verstehe ich das richtig, dass es bei der speicher Funktion dann so aussehen muss:
if(auswahl == 'S' || auswahl == 's') { printf("\nGeben Sie einen Dateinamen ein (z.B.: Test.txt): "); scanf("%s", dateiname); FILE *fp; fp = fopen(dateiname, "wb"); lager_ptr->next = head; if(lager_ptr->next == NULL) { printf("\nListe ist leer!\n\n"); return; } while(lager_ptr->next != NULL) { fwrite(lager_ptr->next, sizeof(struct lagerverwaltung),1,fp); lager_ptr->next = lager_ptr->next->next; } fclose(fp); printf("\nSpeichern erfolgreich abgeschlossen!\n\n\n"); _getch(); system("cls"); break;
-
Ne.
while(lager_ptr->next != NULL) lager_ptr = lager_ptr->next; //bis zum letzten Element springen lager_ptr->next = (struct lagerverwaltung *)malloc(sizeof *lager_ptr->next); //Speicher für neues Element holen lager_ptr->next->next = NULL; //neues letztes Element lager_ptr->next->Artikelnummer = bla; //gerade mit fread gelesene Werte in neue Struktur eintragen lager_ptr->next->... = ...; ...
-
lager_ptr->next = head; :confused: while(lager_ptr != NULL) { fwrite(lager_ptr, sizeof(struct lagerverwaltung),1,fp); lager_ptr = lager_ptr->next; }
-
nwp2 schrieb:
lager_ptr->next->Artikelnummer = bla; //gerade mit fread gelesene Werte in neue Struktur eintragen
nene...
lager_ptr = lager_ptr->next; lager_ptr->Artikelnummer = bla; //gerade mit fread gelesene Werte in neue Struktur eintragen ...
-
@nwp2 & nooblolo: Vielen Dank. Es funktioniert endlich. Ich war schon echt am verzweifeln. Viel Dank nochmal.