String Array
-
Hallo,
ich habe eine Textdatei, in denen Dateinamen stehen. Z.B.:
foo.txt:
Datei1.bla
NochEineDatei.foo
Blub.barIch möchte nun alle Zeilen in ein Array von Strings lesen (ein String pro Zeile), allerdings weiß ich nicht wie viele Zeilen die Datei hat.
Meine 2 Fragen:
- Wenn ich die Größe eines Strings auch noch flexibel halten möchte (sprich beliebig lange Dateinamen sind möglich), dann wäre meine Datenstrukur vermutlich ein char** oder? Sehe ich das richtig, dass ich mein Einlescode in Pseudocode(!) dann so aussehen würde:
Datei komplett lesen int N = anzahl Zeilen char** strings = malloc(N * sizeof(char)) Dateizeiger zurücksetzen char line[1000]; int i = 0; while(!EOF) { read(file, line) int lineLen = strlen(line) strings[i] = malloc(lineLen) strcpy(strings[i++], line) }
Stimmt das so?
- Wie würde meine Datenstruktur aussehen, wenn ich die maximale Länge eines Dateinamens festlege? Also z.B. jeder Dateiname ist maximal 20 Zeichen lang. Dann bräuchte ich ja ein flexibel langes Array von festen char Arrays. Wie sieht das aus? Und wie würde ich dann die Datenstrukur erzeugen?
Danke!
-
- Nein
#define MAXZEILENLAENGE 20 #define MAXZEILENZAHL 1000 char werte[MAXZEILENZAHL][MAXZEILENLAENGE];
-
Ein "Nein" alleine hift mir garnichts.
Und Frage 2 hast du offenbar nicht verstanden.
Hoffe auf weitere Antworten. Im Idealfall diesmal von Leuten mit Ahnung^^
-
was wutz geschrieben hat stimmt schon so =b
zum 1.): char ** stimmt schon so, aber ne unbegrenzte anzahl an speicher kannst du nicht reservieren, denn ich glaube kaum dass du nen speicher von "unendlich"
hast. sprich es muss eine obergrenze geben. diese wird normalerweise, wie schon
von wutz geschrieben, mit konstanten angegeben.2.): was wutz geschrieben hat, wäre mir als erstes auch gleich in den sinn
gekommen. wenn du was anderes meinst, dann beschreibe dein problem besser.ach ja, wutz hat ahnung, mehr als du. aber wenn du dein problem nicht genau
beschreibst, kann nicht mal ein programmierer der seit 30 jahre programmieren
sollte sagen was du meinst.
-
In C++ würde man für so etwas einen
std::vector<std::string>
nehmen, du könntest dir diese Funktionalität nachprogrammieren.Eigentlich würde auch schon ein "growable array" reichen, deren einzelne Elemente aus einem char-Zeiger bestehen. Es ist zwar mehr Verwaltungs- und Programmieraufwand, hält sich aber dennoch in Grenzen:
typedef struct _MyData { char* c; }MyData; void mdFree(MyData* d) { free(d->c); } typedef struct _MyVector { MyData* d; size_t capacity; size_t size; }MyVector; void mvInit(MyVector* mv, size_t initialsize) { // mv->d allokieren (sizeof(MyData)*initialsize) // mv->capacity auf initialsize setzen, mv->size auf 0 } void mvPushBack(MyVector* mv, const char* v) { if(size>=capacity) { // per realloc neuen Speicher anfordern, am Besten sollte sich die bisherige Größe verdoppeln, // also falls vorher 20 Elemete Platz hatten, Speicher für 40 Elemente anfordern u.s.w. // Anschließend mv->capacity neu setzen } // mv->size inkrementieren // Speicher für mv->d[mv->size] anfordern und den string kopieren } // Lesezugriff const char* GetElem(const MyVector* mv, size_t index) { // prüfen, ob Index < mv->size, wenn ja, NULL zurückgeben return mv->d[index]; } void mvFree(MyVector* mv) { //Aufruf von mdFree für jedes Element, anschließend Freigabe von mv->d und Zurücksetzen von mv->size und mv->capacity } .. MyVector vec; char line[MAX_LINELEN]; mvInit(&vec); // in einer Schleife mit fgets die Zeichen einlesen und // mvPushBack(&vec, line) aufrufen .. mvFree(&vec);
Das ist nur ein erster Ansatz, mvInsert und Ähnliches kann zwar implementiert werden, die Funktionalität brauchst du aber in deinem Fall sowieso nicht.
-
itedvo schrieb:
was wutz geschrieben hat stimmt schon so =b
Nein, es stimmt nicht.
itedvo schrieb:
zum 1.): char ** stimmt schon so, aber ne unbegrenzte anzahl an speicher kannst du nicht reservieren, denn ich glaube kaum dass du nen speicher von "unendlich"
hast. sprich es muss eine obergrenze geben. diese wird normalerweise, wie schon
von wutz geschrieben, mit konstanten angegeben.Wo steht denn irgendwas davon, dass ich unendlich viel Speicher brauche? Das sind simple Dateinamen in einer simplen Datei. Da können 10 oder 40 Namen drin stehen. Ich will mir halt einfach nur keine Gedanken machen, wieviele Zeilen nun kommen. Was soll dann bitte an meinem Code falsch sehen? (Abgesehen von dem Flüchtigkeitsfehler, dass ich sizeof(char) statt richtigerweise sizeof(char*) geschrieben habe.
itedvo schrieb:
2.): was wutz geschrieben hat, wäre mir als erstes auch gleich in den sinn
gekommen. wenn du was anderes meinst, dann beschreibe dein problem besser.Das ist einfach nur ein statisches Array. Da ist garnichts dynamisch. Ich habe in meiner Frage 2 doch klipp und klar gesagt, dass nur die Länge der DATEINAMEN fix sein soll, nicht aber die ANZAHL der Zeilen (sprich Dateinamen). Bei wutz ist beides statisch, ergo unbrauchbar.
-
Der Datentyp, nach dem du suchst, ist ein char (*)[21] (21 wegen des Sentinels). Allokation etwa
char (*vec)[21] = malloc(laenge * sizeof(char[21]));
Wenn du mit einem char** arbeitest, gibt es einen großen Haufen möglicher Allokationsschemata. Das einfachste dürfte Folgendes sein:
char **vec = malloc(anzahl_strings * sizeof(char*)); // Später: vec[0] = malloc(laenge_string1); // sizeof(char) ist immer 1
Natürlich müssen die Strings, wenn sie einzeln alloziert werden, auch einzeln freigegeben werden!
Wenn es sich (so lese ich das) nur darum handelt, die Zeilen einer Datei in ein String-Array zu bekommen, du also die Gesamtlänge des Inhalts vorher kennst, bietet sich noch an, die Strings direkt hintereinander im Speicher zu halten. Ich stelle mir das etwa so vor:
#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { FILE *fd; char *heap, **string_vector = NULL, *p; long len; size_t n, chunks = 0, i; size_t const CHUNKSIZE = 32; fd = fopen(__FILE__, "r"); fseek(fd, 0L, SEEK_END); len = ftell(fd); fseek(fd, 0L, SEEK_SET); heap = malloc(len + 1); fread(heap, 1, len, fd); heap[len] = '\0'; for(n = 0, p = heap; p = strchr(p, '\n'); ++n) { if(n >= chunks * CHUNKSIZE) { char **q = realloc(string_vector, sizeof(char*) * (++chunks * CHUNKSIZE)); if(!q) { // Ggf. sinnvolle Fehlerbehandlung hier exit(-1); } string_vector = q; } *p = '\0'; string_vector[n] = ++p; } // Eine leere letzte Zeile wird üblicherweise ignoriert if(string_vector[n - 1][0] == '\0') --n; for(i = 0; i < n; ++i) { printf("%2d: %s\n", i, string_vector[i]); } free(heap); free(string_vector); fclose(fd); return 0; }
-
Genau das habe ich gesucht. Endlich jemand mit Ahnung!
Danke seldon!