Datei zeilenweise einlesen bei unterschiedlicher Zeilenlänge
-
Man hat eine Datei mit maximal 100 Fließkommazahlen pro Zeile in der Form:
1.5;3.5;7.3;77;30
5.8;7.7;3.4;9.9;40;50;60;70
1.1;2.2;3.3
...Die Anzahl der Zeilen ist undefiniert.
Nun soll man die Datei öffnen und diese zeilenweise einlesen. Als erstes dachte ich daran mit fgets die Zeilen zu lesen und dann in ein zweidimensionales Array zu schreiben. Das ist vermutlich nicht der richtige Ansatz, jedenfalls komme ich so nicht weiter.
Ziel ist es dann letztlich, die Zahlen per Bubblesort zu sortieren und in eine neue Datei zu schreiben.
Wie würde man sowas angehen, ich komme an folgender Stelle einfach nicht mehr weiter, mir fehlt eine Möglichkeit die Strings zu trennen, strtok() in Verbindung mit fgets() scheint nicht zu klappen.
#include <stdio.h> int main() { char dArray[100][100]; char *pc; FILE *pFile; int i, j; // Open file for reading pFile = fopen("C:\\Users\\Me\\Documents\\zahlen.txt", "r"); // error handling if (pFile == 0) { printf("Cannot open file!"); } else { for (i = 0; i < 100; i++) { for (j = 0; j < 100; j++) { // Read from file pc = fgets(dArray[i][j], 100, pFile); } } // Closing the file fclose(pFile); } return 0; }
-
was sagt denn der Compiler zu Zeile 25?
dArray[i][j] ist ein char. Platz für ein Zeichen
fgets erwartet aber eine Adresse an der Stelle.Sollen die Zeilen sortiert werden oder alle Zahlen in einer Zeile oder alle Zahlen egal wo diese stehen?
-
DirkB schrieb:
was sagt denn der Compiler zu Zeile 25?
dArray[i][j] ist ein char. Platz für ein Zeichen
fgets erwartet aber eine Adresse an der Stelle.Zeile 25 müsste wohl
pc = fgets(&dArray[i][j], 100, pFile);
lauten und ich sollte ja eigentlich nicht ein Zeichen sondern mehrere bis zu dem Delimiter ; einlesen. Das Problem ist aber, dass beim jeweils letzten Element der Delimiter fehlt. Daher würde es evtl. mehr Sinn machen, das Ganze wirklich zeilenweise einzulesen.
DirkB schrieb:
Sollen die Zeilen sortiert werden oder alle Zahlen in einer Zeile oder alle Zahlen egal wo diese stehen?
Es sollten tatsächlich alle Zahlen sortiert werden, egal wo diese stehen.
-
joe_dimaggio schrieb:
Zeile 25 müsste wohl
pc = fgets(&dArray[i][j], 100, pFile);
Nein richtig wäre:
pc = fgets(&dArray[i][j], 1, pFile); // ein Zeichen (aber dafür nimmt man fgetc //oder pc = fgets(dArray[i], 100, pFile); // dann aber ausserhalb der j-Schleife
Das ist aber alles nicht das, was du möchtest, das dies nur 10000 Zeichen bzw 100 Zeile einliest. Du hast aber von 100 Zahlen pro Zeile, bei unbekannter Zeilenanzahl geschrieben.
Sind die Zahlen und die ; ohne Leerzeichen hintereinander ?
dann gehtdouble zahl; char trenner; size_t anzahl = 0; while (fscanf(pFile ,"%lf%c", &zahl, &trenner) != 2) { printf("%f;", zahl); anzahl++; }
wenn doch Leerzeichen da sind, dann müsste
while (fscanf(pFile ,"%lf%*[ ]%c", &zahl, &trenner) != 2) //ungetestet { ...
while (fscanf(pFile ,"%lf%*[^;\n]%c", &zahl, &trenner) != 2) //ungetestet { ...
Das %*[^;\n] liest alles ausser ; und \n ein und speichert es nicht ab (wegen
Du brauchst nur noch ein double-Array, das groß genug ist um die zahl darin abzulegen.
-
Danke für den Hinweis mit fscanf, mittlerweile hänge ich jedoch an Zeile 49. Da bricht fscanf einfach aus der while Schleife raus, wieso verstehe ich nicht. Bei != 2 wie du meintest geht er erst gar nicht in die Schleife.
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> void bubble(double *array, int elemente); int main() { double dArray[10000]; FILE *pFile; FILE *pFile2; int i = 0; int j = 0; int k = 0; int l; double zahl; char trenner = ';'; char trenner2; srand(time(NULL)); // Open file for reading pFile = fopen("C:\\Users\\Me\\Documents\\zahlen1.txt", "w+"); pFile2 = fopen("C:\\Users\\Me\\Documents\\zahlen2.txt", "w+"); // error handling if (pFile == 0 || pFile2 == 0) { printf("Cannot open one of the files!"); } else { //fuelle datei zahlen1.txt mit 100 x 100 fliesskommazahlen, die mit rand() generiert werden for (k = 0; k < 10000; k++) { dArray[k] = (double)rand(); fprintf(pFile, "%lf%c", dArray[k], trenner); if ((k + 1) % 100 == 0) { fprintf(pFile, "\n"); } } while (fscanf(pFile, "%lf%c", &zahl, &trenner2) > 0) { dArray[i] = zahl; //printf("%lf\n", zahl); i++; } bubble(dArray, i + 1); for (j = 0; j < i; j++) { //printf("%lf\n", dArray[j+1]); fprintf(pFile2, "%lf%c", dArray[j + 1], trenner); if ( (j + 1) % 100 == 0 ) { fprintf(pFile2, "\n"); } } // Closing the files fclose(pFile); fclose(pFile2); } return 0; } void bubble(double *array, int elemente) { int i; double temp; while (elemente--) { for (i = 1; i <= elemente; i++) { if (array[i - 1] > array[i]) { temp = array[i]; array[i] = array[i - 1]; array[i - 1] = temp; } } } }
-
War doch richtig, dass ich ungetestet geschrieben habe
Da muss == 2 stehen, da scanf die Anzahl der gelesenen Element zurückgibt.
(Bei den anderen beiden könnte auch == 3 nötig sein)
Aber lass ruhig das > 0 da stehen. So kannst du auch den letzten Wert aus der letzten Zeile ablegen, wenn dort kein '\n' mehr steht.Nach der Schleife aus Zeile 36 steht der Schreib-Lese-Zeiger am Ende der Datei.
Den musst du erst wieder auf die Position setzen, von der du lesen willst.
(Darum sind die "+"-Modi nicht so einfach zu handhaben).
Schließen und wieder öffnen wäre eine MöglichkeitDa du an den Anfang willst, kannst du rewind nehmen.
-
DirkB schrieb:
Da du an den Anfang willst, kannst du rewind nehmen.
Daran hatte ich natürlich nicht gedacht. Aber jetzt geht es, danke!
-
Du solltest nochmal deine Indizes bei bubblesort überprüfen.
Sowohl in der Funktion als auch beim Aufruf.double dArray[10000] = { 0.0}; // Array mit 0 initialsisieren .... // Beim füllen (besser wäre ohn das Array auszukommen) for (k = 0; k < 200; k++) // Weniger Zahlen { dArray[k] = (double)rand() + 1.0; // keine 0 in dem Array ... // nach dem schreiben Array wieder mit 0 füllen memset(dArray, 0, sizeof(dArray)); rewind ....
Es darf dann keine 0 im sortieretn Array auftauchen.