DAtei öffnen --- auslesen
-
hallo ihr, besonders AJ *g*
ich brauch nochmal hilfe. um alles zu verstehen. wieso da nun ein pointer ist etc.
nochmal mein code bis jetzt:
#include <stdio.h> #include <string.h> #define INPUTFILE "Air_Plus_Beispiel.csv" //inputfile wird definiert #define OUTPUTFILE "test.csv" //outputfile wird definiert #define DELIM ";" //ab ; neu int main (void) { FILE * input_stream, *output_stream; //<-- ? char line[BUFSIZ]; //<-- ? char *tokens[BUFSIZ]; //<-- ? int i; char * temptok; //<-- ? char file; printf("********** Datei-Auswahl **********\n\n"); printf("1. Airplus\n"); printf("2. Vodafone\n"); printf("3. Beenden\n\n"); printf("Bitte waehlen Sie nun, welche Datei sie verarbeiten wollen.\n\n"); printf("Ihre Eingabe: "); scanf("%i",&file); printf("\n\n\n"); switch(file) { case 1: printf("********** Airplus **********\n"); input_stream = fopen( INPUTFILE, "r"); // Eingabe oeffnen (lesen) if (input_stream == NULL) //bei nicht vorhandener datei... { printf( "\nThe file '%s' was not opened\n", INPUTFILE );//fehlermeldung exit(2); }; output_stream = fopen( OUTPUTFILE, "a"); //Ausgabe oeffnen (anhängen) if (output_stream == NULL) //bei nicht vorhandener datei... { printf( "\nThe file '%s' was not opened\n", OUTPUTFILE );//fehlermeldung exit(2); }; while (!feof(input_stream)) //Solange kein End-Of-File in der Eingabe... { fgets (line, BUFSIZ, input_stream); //<-- ? i = 0; temptok = line; //<-- ? while ( (tokens[i] = strtok(temptok, DELIM)) != NULL) //strtok erwartet folgende Parameter: //temptok ist die zu splittende Zeile beim 1. Aufruf und NULL bei nachfolgenden Aufrufen; //der zweite Parameter sind die Grenzen der Tokens // Konstante DELIM oben auf ";" definiert //strtok gibt einen Zeiger auf den nächsten Token zurück oder NULL, wenn kein Token mehr da ist //(String zu Ende tokenisiert) //weise tokens[i] die Adresse des nächstens Tokens zu; wenn die Adresse nicht NULL ist, mache Folgendes: ... { temptok = NULL; i++; }; //schreiben in datei fprintf (output_stream, "\n%s;",tokens[3]); fprintf (output_stream, "%s;",tokens[4]); fprintf (output_stream, "%s;",tokens[5]); fprintf (output_stream, "%s;",tokens[13]); fprintf (output_stream, "%s;",tokens[17]); fprintf (output_stream, "%s;",tokens[18]); fprintf (output_stream, "%s;",tokens[19]); fprintf (output_stream, "%s;",tokens[25]); fprintf (output_stream, "%s;",tokens[27]); fprintf (output_stream, "%s;",tokens[31]); fprintf (output_stream, "%s;",tokens[38]); }; //schließen der beiden datein fclose (output_stream); fclose (input_stream); break; case 2: printf("********** Vodafone **********\n"); break; case 3: printf("********** Programm wird beendet **********\n"); break; default : printf("********** Falsche Eingabe! **********\n"); break; } system("pause"); }
AJ, kannst du das programm nachvollziehen und evtl kommentare dazu schreiben, was genau in den einzelnen zeilen passiert? ich verlier wiedermal den überblick
hab nun das, wo ich wirklich mir nicht viel bei denken kann mit "//<-- ?" beschrieben
-
OK
#include <stdio.h> #include <string.h> #define INPUTFILE "Air_Plus_Beispiel.csv" //inputfile wird definiert #define OUTPUTFILE "test.csv" //outputfile wird definiert #define DELIM ";" //ab ; neu int main (void) { FILE * input_stream, *output_stream; //Dateizeiger, zeigt auf Informationen über eine geöffnete Datei (nach fopen()) char line[BUFSIZ]; //Speicherbereich für eingelesene Zeile char *tokens[BUFSIZ]; //Zeigerarray zum Speichern der Zeiger auf die einzelnen Tokens int i; char * temptok; //Hilfszeiger für strtok() char file; printf("********** Datei-Auswahl **********\n\n"); printf("1. Airplus\n"); printf("2. Vodafone\n"); printf("3. Beenden\n\n"); printf("Bitte waehlen Sie nun, welche Datei sie verarbeiten wollen.\n\n"); printf("Ihre Eingabe: "); scanf("%i",&file); printf("\n\n\n"); switch(file) { case 1: printf("********** Airplus **********\n"); input_stream = fopen( INPUTFILE, "r"); // Eingabe oeffnen (lesen) if (input_stream == NULL) //bei nicht vorhandener datei... { printf( "\nThe file '%s' was not opened\n", INPUTFILE );//fehlermeldung exit(2); }; output_stream = fopen( OUTPUTFILE, "a"); //Ausgabe oeffnen (anhängen) if (output_stream == NULL) //bei nicht vorhandener datei... { printf( "\nThe file '%s' was not opened\n", OUTPUTFILE );//fehlermeldung exit(2); }; while (!feof(input_stream)) //Solange kein End-Of-File in der Eingabe... { fgets (line, BUFSIZ, input_stream); //liest eine Zeile von einer Datei ein i = 0; temptok = line; //weißt die gespeicherte Adresse in line auf temptok zu; temptok zeigt somit auf die gleiche Adresse wie line while ( (tokens[i] = strtok(temptok, DELIM)) != NULL) //strtok erwartet folgende Parameter: //temptok ist die zu splittende Zeile beim 1. Aufruf und NULL bei nachfolgenden Aufrufen; //der zweite Parameter sind die Grenzen der Tokens // Konstante DELIM oben auf ";" definiert //strtok gibt einen Zeiger auf den nächsten Token zurück oder NULL, wenn kein Token mehr da ist //(String zu Ende tokenisiert) //weise tokens[i] die Adresse des nächstens Tokens zu; wenn die Adresse nicht NULL ist, mache Folgendes: ... { temptok = NULL; i++; }; //schreiben in datei fprintf (output_stream, "\n%s;",tokens[3]); fprintf (output_stream, "%s;",tokens[4]); fprintf (output_stream, "%s;",tokens[5]); fprintf (output_stream, "%s;",tokens[13]); fprintf (output_stream, "%s;",tokens[17]); fprintf (output_stream, "%s;",tokens[18]); fprintf (output_stream, "%s;",tokens[19]); fprintf (output_stream, "%s;",tokens[25]); fprintf (output_stream, "%s;",tokens[27]); fprintf (output_stream, "%s;",tokens[31]); fprintf (output_stream, "%s;",tokens[38]); }; //schließen der beiden datein fclose (output_stream); fclose (input_stream); break; case 2: printf("********** Vodafone **********\n"); break; case 3: printf("********** Programm wird beendet **********\n"); break; default : printf("********** Falsche Eingabe! **********\n"); break; } system("pause"); }
Funktioniert dein Programm eigentlich fehlerfrei? Zumindest an einer Stelle dürfte was falsch laufen. Schau dir mal deine Ausgabedatei an, speziell die letzten zwei Zeilen.
-
ja, so ganz funktioniert es noch nicht
beim schreiben in die neue datei kommen ein paar sachen ein wenig "komisch" an *grübel*
-
Also ein Fehler liegt schon mal daran, dass du den Rückgabewert von fgets() nicht überprüfst. Auch wenn fgets() die letzte Zeile in der Datei gelesen hat, erkennt feof() noch nicht, dass das Dateiende erreicht wurde. Erst wenn das Dateiende "gelesen" wird. Und in dem Fall liefert fgets() 0 zurück. Du musst also den Rückgabewert von fgets() abprüfen, ob er ungleich 0 ist. Wenn ja, dann soll der Code darunter ausgeführt werden, wenn nein, dann nicht.
Dann kommt es mir noch mit dem tokens Array komisch vor. Daraus solltest du am besten ein zweidimensionales Array machen:
char tokens[ANZ_SPALTEN][BUFSIZ];
Zusätzlich brauchst du dann noch einen Zeiger wie temptok (aber nicht temptok selber benutzen).
Den Rückgabewert von strtok weißt du dann auf den neuen Zeiger zu und in der Schleife kopierst du per strcpy() den Inhalt auf den der neue Zeiger zeigt in das tokens-array.
Also so:
... char tokens[ANZ_SPALTEN][BUFSIZ]; char *akt_token; //neuer Zeiger, der auf das aktuelle Token zeigt ... for(i = 0; (akt_token = strtok(temptok, DELIM)) != NULL && i < ANZ_SPALTEN; ++i) { strcpy(tokens[i], akt_token); temptok = NULL; } ...
-
und wo genau muss ich
for(i = 0; (akt_token = strtok(temptok, DELIM)) != NULL && i < ANZ_SPALTEN; ++i) { strcpy(tokens[i], akt_token); temptok = NULL; }
jetzt einsetzen?
-
wird das mit dem 2 dimensionalen array nicht viel komplizierter für mich?
oder muss ich wirklich NICHTS weiter ändern im code, außer was du mir geschrieben hattest?
-
AJ schrieb:
OK
Funktioniert dein Programm eigentlich fehlerfrei? Zumindest an einer Stelle dürfte was falsch laufen. Schau dir mal deine Ausgabedatei an, speziell die letzten zwei Zeilen.
was genau meintest du damit?
-
Troja2k schrieb:
und wo genau muss ich
for(i = 0; (akt_token = strtok(temptok, DELIM)) != NULL && i < ANZ_SPALTEN; ++i) { strcpy(tokens[i], akt_token); temptok = NULL; }
jetzt einsetzen?
Das ersetzt deine bisherige strtok() Schleife
Troja2k schrieb:
wird das mit dem 2 dimensionalen array nicht viel komplizierter für mich?
oder muss ich wirklich NICHTS weiter ändern im code, außer was du mir geschrieben hattest?
Es wird dadurch nicht wirklich komplizierter, aber auf jeden Fall sicherer.
Mehr musst du wirklich nicht ändern. Nur eben das behandeln der Daten mit strtok() und die Abfrage vom Rückgabewert von fgets().
Troja2k schrieb:
AJ schrieb:
OK
Funktioniert dein Programm eigentlich fehlerfrei? Zumindest an einer Stelle dürfte was falsch laufen. Schau dir mal deine Ausgabedatei an, speziell die letzten zwei Zeilen.
was genau meintest du damit?
Normalerweise müssten die zwei letzten Zeilen genau gleich sein und es müsste eine Zeile mehr existieren als in der Quelldatei.
Wie gesagt erst wenn fgets() (oder eine andere Lesefunktion) das Dateiende auch wirklich gelesen hat, erkennt feof() das Dateiende.
In deinem Fall würde das heißen, dass du die letzte Zeile einliest (der Dateizeiger steht vor dem Dateiende) und auswertest, dann kommt feof() und erkennt nicht, dass der Dateizeiger schon am Dateiende steht, da das Dateiende noch nicht gelesen wurde. Also wird die Schleife nochmal ausgeführt. fgets() liest nun das Dateiende und gibt 0 als Erkennung eines "Fehlers" zurück. Da du das aber nicht auswertest wird der Quellcode ganz normal weiterverarbeitet, d. h. die zuvor gelesene Zeile wird nochmal fälschlicherweise verarbeitet und erst jetzt erkennt feof(), dass das Dateiende erreicht wurde.
-
#include <stdio.h> #include <string.h> #define INPUTFILE "Air_Plus_Beispiel.csv" #define OUTPUTFILE "test.csv" #define DELIM ";" int main (void) { FILE * input_stream, *output_stream; //Dateizeiger, zeigt auf Informationen über eine geöffnete Datei (nach fopen()) char line[BUFSIZ]; //Speicherbereich für eingelesene Zeile //char line [BUFSIZ]; //Zeigerarray zum Speichern der Zeiger auf die einzelnen Tokens int i; char * temptok; //Hilfszeiger für strtok() char file; char tokens[ANZ_SPALTEN][BUFSIZ]; char *akt_token; //neuer Zeiger, der auf das aktuelle Token zeigt printf("********** Datei-Auswahl **********\n\n"); printf("1. Airplus\n"); printf("2. Vodafone\n"); printf("3. Beenden\n\n"); printf("Bitte waehlen Sie nun, welche Datei sie verarbeiten wollen.\n\n"); printf("Ihre Eingabe: "); scanf("%i",&file); printf("\n\n\n"); switch(file) { case 1: printf("********** Airplus **********\n"); input_stream = fopen( INPUTFILE, "r"); // Eingabe oeffnen (lesen) if (input_stream == NULL) { printf( "\nThe file '%s' was not opened\n", INPUTFILE );//fehlermeldung exit(2); }; output_stream = fopen( OUTPUTFILE, "a"); //Ausgabe oeffnen (anhängen) if (output_stream == NULL) { printf( "\nThe file '%s' was not opened\n", OUTPUTFILE );//fehlermeldung exit(2); }; while (!feof(input_stream)) //Solange kein End-Of-File in der Eingabe... { fgets (line, BUFSIZ, input_stream); //liest eine Zeile von einer Datei ein i = 0; temptok = line; for(i = 0; (akt_token = strtok(temptok, DELIM)) != NULL && i < ANZ_SPALTEN; ++i) { strcpy(tokens[i], akt_token); temptok = NULL; } //strtok erwartet folgende Parameter: //temptok ist die zu splittende Zeile beim 1. Aufruf und NULL bei nachfolgenden Aufrufen; //der zweite Parameter sind die Grenzen der Tokens // Konstante DELIM oben auf ";" definiert //strtok gibt einen Zeiger auf den nächsten Token zurück oder NULL, wenn kein Token mehr da ist //(String zu Ende tokenisiert) //weise tokens[i] die Adresse des nächstens Tokens zu; wenn die Adresse nicht NULL ist, mache Folgendes: ... //schreiben in datei fprintf (output_stream, "\n%s;",tokens[3]); fprintf (output_stream, "%s;",tokens[4]); fprintf (output_stream, "%s;",tokens[5]); fprintf (output_stream, "%s;",tokens[13]); fprintf (output_stream, "%s;",tokens[17]); fprintf (output_stream, "%s;",tokens[18]); fprintf (output_stream, "%s;",tokens[19]); fprintf (output_stream, "%s;",tokens[25]); fprintf (output_stream, "%s;",tokens[27]); fprintf (output_stream, "%s;",tokens[31]); fprintf (output_stream, "%s;",tokens[38]); }; //schließen der beiden datein fclose (output_stream); fclose (input_stream); break; case 2: printf("********** Vodafone **********\n"); break; case 3: printf("********** Programm wird beendet **********\n"); break; default : printf("********** Falsche Eingabe! **********\n"); break; } system("pause"); }
mmh..nu gibbet fehler
16 `ANZ_SPALTEN' undeclared (first use in this function)
-
Ich dachte du würdest verstehen, was ich mit ANZ_SPALTEN bezwecke. Kleiner Tipp: Es ist sowas ähnliches wie DELIM oder BUFSIZ ;).
-
ähm *ggg* nein, weiß ich nicht. kannte ja DELIM und BUFSIZ vorher nicht. hab noch nie was davon gehört gehabt
-
Aber für was es ist, kannst du dir schon denken, oder??
Du musst es im Prinzip nur so machen wie bei DELIM:
//Anzahl der Spalten in einer Zeile #define ANZ_SPALTEN
Hinter ANZ_SPALTEN musst du natürlich noch den passenden Wert schreiben ;).
-
*wieder AJ belästigt*
ja, für DENIM hab ich ; gesetzt, welches ja immer am "ende" eines wertes steht.
aber was steht nach unten hin
-
Was nach unten hin steht?
Irgendwie, glaub ich, verstehst du nicht was ich meine.
ANZ_SPALTEN ist kein Trenner. Überleg doch mal was ANZ_SPALTEN heißt. Eigentlich brauchst du ja nur den Kommentar, den ich extra dazugeschrieben habe lesen. Wenn du weißt was es heißt (was eigentlich mehr als offensichtlich ist), dann weißt du auch welchen Wert bzw. welche Zahl du hinschreiben musst.
-
*grml*
#define ANZ_SPALTEN "45"
wahrscheinlich auch falsch, weil das guckt dann ja wo eine 45 steht, oder?
die datei die ich einlese hat 45 spalten
-
Jetzt bist du der Sache schon ganz nahe.
Der Compiler schaut aber nicht ob da irgendwo eine 45 steht, sondern er schaut, ob da ANZ_SPALTEN steht und ersetzt das momentan durch "45" (inclusive Anführungszeichen). Allerdings wirst du da noch Fehler bekommen, weil es so keinen Sinn macht (so würde es der Compiler ersetzen; BUFSIZ würde er natürlich auch durch eine Zahl ersetzen ;)):... char tokens["45"][BUFSIZ]; ...
Lass einfach die Anführungszeichen weg und schon passt es :).
(so sollte es dann vom Compiler ersetzt werden)
... char tokens[45][BUFSIZ]; ...
So würde es doch auch richtiger aussehen, oder?
-
so, es läuft
du bist klasse!
noch eine frage.
wenn ich jetzt die csv datei mitexel öffne, um zu gucken, wie das dort hineingeschrieben wurde, dann geht es immernoch nicht wirklich . d.h. es ist immernoch verschoben.soll ich dir die datei mal per email schicken, damit du siehst wie ich es meine?
-
Ja mach mal. Kann sie mir aber erst morgen vornehmen, sorry.
Schau dir die Datei einfach mal mit dem notepad (Start -> Ausführen -> notepad) an, vielleicht findest du dann den Fehler.
-
kann nichts auffälliges finden, was daran schuld sein könnte.
hab dir die datein mal zum web.de postfach geschickt.
-
nochmal genauer :
- in der ersten zeile gibt mein blödes prog ein paar sachen doppelt aus.
- und es schreibt das letzte eingelesene element in eine neue zeile, was das ganze durcheinander bringt