Datei einlesen, Struct erstellen, Problem bei Allocate und Zeiger/arrays
-
Hallo!
Wie bereits mein Titel schon sagt, versuche ich folgende Schritte zu programmieren:
-TExtdatei zeilenweise einlesen
- Zeile parsen - Infos in eine neu generierte Struktur packen
- diese neue Struktur in ein Array hinzufügenHier habe ich mehrere Probleme:
- ich muss doch dass Array vorher allocaten, aber wie, wenn ich nicht weiss, wie viele ich zeilen in der Datei haben werde bzw. wie viele Strukturen ich generieren werde?
Mein Programm sieht so aus, also erst die Struktur:
typedef struct inf { int start; int start_snd; int length; } information;
Ich lass jetzt mal das ganze einlesen weg und das parsen, also wichtig ist nur das generieren der Struktur und dann hinzufügen.
information *all_infos; // wie allocaten? // 2) Ist das auch ein array, oder brauche ich **all_infos dafür? diese Zeiger sind noch sehr verwirrend :( int line_length = 200; char line[line_length]; while(fgets(line, line_length, file)!= NULL) { /*Parsen usw...*/ int st, st_snd, len; // jetzt generieren und neu hinzufügen information *info = (information*) malloc(sizeof(information)); info->start = st; info->start_snd = st_snd; info->length = len; // 3) WIE fuege ich jetzt das info in das array rein??? }
-
- ich muss doch dass Array vorher allocaten, aber wie, wenn ich nicht weiss, wie viele ich zeilen in der Datei haben werde bzw. wie viele Strukturen ich generieren werde?
Ein Array muss man, wie du selbst schon festgestellt hast, VORHER definieren, d.h. dabei auch die Größe festlegen.
Nachträglich lassen sich Arrays nicht mehr in ihrer Größe verändern.(auch wenn dieser Aberglaube von Fachbuchautoren,Tutorialschreiberlingen,Hochschullehrern immer wieder verbreitet wird).
Deshalb musst du auf dynamischen Speicher (malloc/calloc/free/realloc) ausweichen.
Dabei musst du dir aber die aktuelle Größeninformation deiner Liste im dynamischen Speicher separat merken und pflegen.typedef struct inf { int start; int start_snd; int length; } information;
Jede gültige Textdateizeile soll eine Struktur diesen Typs befüllen?
-
[quote="Wutz"]
Jede gültige Textdateizeile soll eine Struktur diesen Typs befüllen?
Genau, also wenn ich eine Datei mit 10 Zeilen habe, habe ich am Ende 10 Strukturen Information in dem Array.
- stimmt dass denn so, wie ich den Speicher für information allocate? In Zeile 15?
- Hier bin ich verwirtt, ist mein "info" jetzt ein Zeiger oder meine Struktur info?
Und wie füge ich jetzt die Struktur "info" in mein Array Hinzu?
-
Dein info ist ein Zeiger auf eine information-Struktur, genau wie dein all_infos.
Hier ein kleines Stück Code, wie man es mit realloc machen könnte.information *all_infos = NULL; size_t all_infos_top = 0; //index des ersten nicht belegten Elements size_t all_infos_size = 0; //Länge des allokierten Speichers in Elementen size_t new_information_index(void) //gibt index auf nächstes freies Element von all_infos zurück { assert(all_infos_top <= all_infos_size); //prüfe ob genug Platz vorhanden ist if(all_infos_top == all_infos_size) { //mehr Platz beschaffen all_infos_size += 16; all_infos = realloc(all_infos, all_infos_size * sizeof(*all_infos)); //prüfe ob allokation fehlgeschlagen ist if(all_infos == NULL) { perror("Oh Gott, Oh Gott"); exit(EXIT_FAILURE); } } return all_infos_top++; } //anhängen information info; //init. info all_infos[new_information_index()] = info; //oder auch all_infos[new_information_index()] = (information) {.start=0, .start_snd=0, .length=0 }; //nicht vergessen free(all_infos);
-
Du kannst einem Array nichts hinzufügen, nur die vorhandenen Elemente im Array befüllen; und was machst du, wenn das Array 'voll' ist?
Nichts kannst du dann mehr mit deinem Array machen.Was ist eigentlich so schwer daran, die immer gleiche Vorgehensweise für einfache C-Programme zu begreifen.
1. Datendesign (typedef)
2. Programmdesign (Funktionen unter Verwendung der typedef)
3. TDDAlso in Gottes Namen zum gefühlt 1000sten Mal:
typedef struct { int start; int start_snd; int length; } Information; typedef struct { Information *info; int z; /* Anzahl Elemente */ } Liste; Information einElement(const char *zeile) { Information i; ... irgendwie i befüllen aus zeile ... return i; } void addiereZuListe(Liste *liste,Information i) { liste->info = realloc(liste->info,++liste->z*sizeof*liste->info); liste->info[liste->z-1]=i; } void freeListe(Liste liste) { free(liste.info); } void printListe(Liste liste) { int i; for(i=0;i<liste.z;++i) printf(...liste.info[i]...); } int main() { Liste liste={0}; ... while(fgets(zeile,1000,f)) addiereZuListe(&liste,einElement(zeile)); ... printListe(liste); freeListe(liste); return 0; }
ungetestet, ohne Fehlerbehandlung
-
gary1195 schrieb:
Vielen Dank für deine Hilfe.
- Gibt es eigentlich einen Grund, wieso du 16 ausgewählt hast, oder ist das nur random?
- ist dein size_t nur als int definiert oder?Habe auch soweit (glaube ich
) die ganze Vorgehensweise verstanden, werde ich gleich ausprobieren. Vielen Dank für die Hilfe!
Wutz schrieb:
Was ist eigentlich so schwer daran, die immer gleiche Vorgehensweise für einfache C-Programme zu begreifen.
- es ist schwer, da ich bis jetzt nur mit Java gearbeitet habe, und da man einfach mit .add() sich neue Elemente im Array speichern lässt - deswegen auch meine Frage, wie man denn "neue Elemente hinzufügt". Deswegen bin ich ja auf diesem Forum, sobald ich an einer Stelle nicht weiter komme.
-
tinchi schrieb:
- Gibt es eigentlich einen Grund, wieso du 16 ausgewählt hast, oder ist das nur random?
Speicher per realloc zu besorgen ist teuer (es dauert). Darum holt man meist Speicher für mehrere Objekte.
Du kannst auch andere Werte nehmen oder auch den Speicher immer verdoppeln.tinchi schrieb:
- ist dein size_t nur als int definiert oder?
size_t
ist ein Standarddatentyp. Er wird durch verschiedene Header der Standardbibliothek bereit gestellt.
http://www.cplusplus.com/reference/cstddef/size_t/