Scratch Geschrieben 26. Januar 2006 Geschrieben 26. Januar 2006 Hallo, ich lese in meinem C Programm eine Datei zeilenweise ein per Funktion. Jetzt möchte ich das ganze in einem Array speichern und zurückgeben an main. Wie kann ich sowas den am besten realisieren? bisher die Funktion zum einlesen der Datei: void readFile(char *pFileName) { FILE *pFile; char buffer[FILEROW]; int i; pFile = fopen(pFileName,"r"); if(pFile != NULL) { i = 0; while(fgets(buffer,FILEROW,pFile)) { i++; printf("Zeile\t%i:\t%s",i,buffer); } fclose(pFile); } } Wie muss der Rückgabewert den sein? Bzw. wie kann ich die Zeilen statt direkt auszugeben in ein Array speichern und zurückgeben mit return? Gruß Scratch Zitieren
Guybrush Threepwood Geschrieben 26. Januar 2006 Geschrieben 26. Januar 2006 such im Forum mal nach dynamisches Array dann findest du ne Erklärung dazu Zitieren
baba007 Geschrieben 26. Januar 2006 Geschrieben 26. Januar 2006 - zuerst schreibst du eine funktion, die die elemente deiner datei zählt - in der main allokierst du den nötigen speicher des arrays - speicherst den pointer in einer variablen p_x - übergibst diesen Pointer auf das erste element des array - fühlst den array - und bist fertig Zitieren
Scratch Geschrieben 27. Januar 2006 Autor Geschrieben 27. Januar 2006 Hi, also danke erstmal für die Antworten. Was haltet ihr von dieser Lösung: int file_countRows(char *pFileName) { FILE *pFile; char strBuffer[ROW]; int i; // Open the file pFile = fopen(pFileName,"r"); if(pFile == NULL) { return -1; } // Count the rows i = 0; while(fgets(strBuffer,ROW,pFile)) { i++; } fclose(pFile); return i; } char** file_read(char *pFileName) { FILE *pFile; char strBuffer[ROW]; int i,j; int iRows; char **pArray; // Count rows of the file iRows = file_countRows(pFileName); if(iRows < 0) { return NULL; } // Allocate space for the array rows pArray = (char **) malloc(iRows * sizeof(char *)); if(pArray == NULL) { printf("Connat allocate enough virtual memory.\n"); return NULL; } // Allocate space for the array cols for(i = 0;i < iRows;i++) { pArray[i] = (char *) malloc(ROW * sizeof(char)); if(pArray[i] == NULL) { printf("Connat allocate enough virtual memory for row %d\n",i); return NULL; } } // Open the file pFile = fopen(pFileName,"r"); if(pFile == NULL) { printf("Connat open file"); return NULL; } // Fill the array i = 0; while(fgets(strBuffer,ROW,pFile)) { strcpy(pArray[i],strBuffer); i++; } fclose(pFile); return pArray; }[/PHP] Vorlage hierfür war ein sehr gutes Beispiel von http://www.pronix.de/pronix-762.html Gruß Scratch Zitieren
Hakawamu Geschrieben 27. Januar 2006 Geschrieben 27. Januar 2006 sieht ganz gut aus. ich würds wohl auch so ähnlich machen Zitieren
Guybrush Threepwood Geschrieben 27. Januar 2006 Geschrieben 27. Januar 2006 ich würde die Zeilen in der Datei nicht vorher zählen, sondern das array entsprechend erweitern. Zitieren
baba007 Geschrieben 27. Januar 2006 Geschrieben 27. Januar 2006 ich würde die Zeilen in der Datei nicht vorher zählen, sondern das array entsprechend erweitern. das würde knallen, wenn du das zur laufzeit allokieren würdest. spätestens nach einem stark ausgelastetem Speicher eines Servers oder so. Das ist quick and dirty Zitieren
Klotzkopp Geschrieben 27. Januar 2006 Geschrieben 27. Januar 2006 das würde knallen, wenn du das zur laufzeit allokieren würdest.Wieso? spätestens nach einem stark ausgelastetem Speicher eines Servers oder so.Ich verstehe nicht, was du damit sagen willst :confused: Das ist quick and dirtyWas genau jetzt? Dieser Ansatz? realloc an sich? Wenn du so überzeugt bist, dann bring doch mal ein paar Gründe für deine Behauptungen. Zitieren
Klotzkopp Geschrieben 27. Januar 2006 Geschrieben 27. Januar 2006 Was haltet ihr von dieser Lösung:Die casts auf den Rückgabewert von malloc sind unnötig und können Fehler verdecken. malloc gibt void* zurück, und der ist in jeden anderen Zeigertyp implizit konvertierbar, da braucht man keinen cast. Zitieren
nic_power Geschrieben 27. Januar 2006 Geschrieben 27. Januar 2006 Hallo, das würde knallen, wenn du das zur laufzeit allokieren würdest. spätestens nach einem stark ausgelastetem Speicher eines Servers oder so. Das ist quick and dirty Wieso das denn? Es ist wesentlich sinnvoller den Speicher während der Laufzeit zu besorgen, da man dann nur das reservieren muss was auch benötigt wird. Nic Zitieren
Guybrush Threepwood Geschrieben 27. Januar 2006 Geschrieben 27. Januar 2006 Eben. Der einzige Grund der mir spontan einfällt der gegen eine dynamische Speicherreservierung bei einem Programm (nicht bei diesem ) sprechen würde ist wenn es sehr performance kritisch ist und die Daten nicht andauernd hin und her geschoben werden sollen... Zitieren
baba007 Geschrieben 28. Januar 2006 Geschrieben 28. Januar 2006 vielleicht habe ich die Speicherverwaltung auch falsch verstanden, aber ist es nicht so, dass nach meinem Vorschlag das System schaut wo finde ich ein geeignetes Plätzchen für mein Array der Länge X, die ich ja kenne und dass nach dem anderen Verfahren, das System irgendwo das erste Element des Arrays setzt und genau von hier an, diesen Array um X - Byte, was ja hier nicht bekannt ist, erweitert ? Das Problem welches ich sehe ist folgendes: 1) man weiss in der Regel nicht wie viele Elemente in der Datei sind 2) malloc immer nur den nächsten Speicherblock nimmt 3) wenn die Datei sehr lang ist, er ggf. auf andere, sich im Speicher befindlichen Elemente, stößt und sie überschreibt oder nicht weiter macht wegen Zugriffsverletzung Liege ich hier falsch ? Wenn ja, erbitte ich einen Link wo ich das vorgehen von Malloc und die tatsächliche Speicherverwaltung nachlesen kann. Zitieren
Guybrush Threepwood Geschrieben 28. Januar 2006 Geschrieben 28. Januar 2006 Ja da liegst du falsch wenn es so wäre dann wäre es ja grausam und du könntest nicht viel mit deinem PC anfangen malloc kuckt natürlich nach ob an der Stelle wo es reserviert genug Platz für alle Daten ist, wenn nicht sucht es eine andere Stelle und wenn es keine findet dann gibt es NULL zurück. Wenn du diesen speicher nun zur Laufzeit erweitern willst und an der Stelle ist nicht genug Platz dann wird er automatisch von realloc an eine Stelle verschoben wo genug Platz dafür ist. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_CRT_malloc.asp http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_realloc.asp Noch ein kleiner Tipp wenn man eh mit realloc arbeiten will kann man sich das malloc sparen. realloc mit NULL als erstem Parameter arbeitet wie malloc. Das eigenet sich somit gut für Schleifen. Zitieren
Klotzkopp Geschrieben 28. Januar 2006 Geschrieben 28. Januar 2006 1) man weiss in der Regel nicht wie viele Elemente in der Datei sindRichtig. Deshalb aber vorher zu zählen, ist ineffizient und unnötig. 2) malloc immer nur den nächsten Speicherblock nimmtDer Begriff "nächster" Speicherblock ist ungünstig gewählt. Unterhalb von malloc liegt das Speichermanagement des Betriebssystems. Das kann mit deinem Speicher machen was es will. Es muss nicht sein, dass zwei Elemente eines Arrays in C im physischen Speicher nebeneinander liegen. Es kann sein, dass sie überhaupt nicht im RAM liegen. Du sorgst dich da um Dinge, auf die du sowieso keinen Einfluss hast, zumindest wenn du ein heute aktuelles Betriebssystem benutzt, um deine Programme auszuführen. 3) wenn die Datei sehr lang ist, er ggf. auf andere, sich im Speicher befindlichen Elemente, stößt und sie überschreibt oder nicht weiter macht wegen ZugriffsverletzungNein, dafür gibt es realloc. Damit kann man ein Array einfach zur Laufzeit vergrößern. Und da es sich nur um ein Array von Zeigern handelt, ist das nicht einmal besonders aufwändig. Zitieren
baba007 Geschrieben 28. Januar 2006 Geschrieben 28. Januar 2006 a ok, danke für den Crashkurs ... also nicht vorher zählen Zitieren
Scratch Geschrieben 30. Januar 2006 Autor Geschrieben 30. Januar 2006 Zitat von Klotzkopp Die casts auf den Rückgabewert von malloc sind unnötig und können Fehler verdecken. malloc gibt void* zurück, und der ist in jeden anderen Zeigertyp implizit konvertierbar, da braucht man keinen cast. Lasse ich den cast weg kommt: cannot convert `void *' to `char *' in assignment Compiler ist gcc. Gruß Scratch Zitieren
Klotzkopp Geschrieben 30. Januar 2006 Geschrieben 30. Januar 2006 Lasse ich den cast weg kommt: cannot convert `void *' to `char *' in assignmentDann compilierst du das vermutlich als C++, denn da gibt es diese implizite Konvertierung von void* nicht. Zitieren
Scratch Geschrieben 30. Januar 2006 Autor Geschrieben 30. Januar 2006 Ok, daran lags ;-) Jetzt hab ich aber noch eine Frage über realloc astrFile = NULL; a = 0; while(!file.eof()) { getline(file,strLine); a++; astrFile = (string *) realloc(astrFile,a * sizeof(string)); astrFile[a].assign(strLine); } file.close();[/PHP] ergibt: "Segmentation fault" Kann es daran liegen das sizeof(string) variabel ist, je nach Länge des Strings? Oder gibt es in C++ vielleicht noch eine viel bessere Lösung für sowas mit vektor oder queue? Zitieren
Klotzkopp Geschrieben 30. Januar 2006 Geschrieben 30. Januar 2006 Die Speicherfunktionen von C darfst du für Klassen nicht benutzen, weil sie keine Konstruktoren oder Destruktoren aufrufen können. Die können nur den Speicherinhalt kopieren, was bei Klassen, die dynamisch Speicher anfordern, zwangsläufig zu Problemen führt. Wenn du aber sowieso C++ benutzt, brauchst du gar kein realloc, denn dafür gibt es in C++ die Container der Standardbibliothek: vector<string> v; while(getline(file, line)) { v.push_back(line); }[/code] Zitieren
Scratch Geschrieben 30. Januar 2006 Autor Geschrieben 30. Januar 2006 Das hatte ich mir fast gedacht ... Danke, danke für die Hilfe und die vielen Tipps!!! Gruß Scratch Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.