CSV Dateien lesen, schreiben, einzelne werte nachträglich ändern

Django6

Cadet 4th Year
Registriert
Nov. 2011
Beiträge
67
Guten Abend

ich habe mal wieder ein Problem etwas zu verstehen

wäre nett wenn mir da jemand helfend zur hand gehen würde :)

folgendes szenario

ich versuche durch eine csv datei zu gehen die ich vorher im quellcode angelegt und/oder geöffnet habe (nich mit r sondern mit a) die daten in eine von mir angelegte struktur zu laden, dann einen vergleich duchzuführen ob eine der zahlen mit einer nutzereingabe übereinstimmt und wenn ja eine in der struktur ein char zu ändern und in die gleiche zeile zu schreib (die alte zeile zu überschreiben)

mein struct sieht wie folgt aus:
Code:
struct kunde
{
    int Kundennummer;
    int Parkscheinnummer;
    int zeit;
    char Dauerparker;
    char bezahlt;
    char Parkplatztyp;
    char ausgefahren;
    char Kennzeichen[10];
};

ich habe es auch schon geschafft das strukt zu füllen und dieses dann in eine zeile der csv datei (die letzte) anzuhängen

nun mein versuch eben beschriebenes zu lösen nach 2 stunden recherche.

Code:
int bezahlen(struct kunde *wagen, FILE *CSV)
{
    int Parkscheinnummer_tmp;
    printf("Geben Sie ihre Parkscheinnummer ein und dr%c \bcken Sie Enter.",ue);
    scanf("%i",&Parkscheinnummer_tmp);
    fflush(stdin);
    rewind(CSV);
    do
    {
        fscanf(CSV,"%i,%i,%i,%c,%c,%c,%c,%s\n",&((*wagen).Kundennummer),&((*wagen).Parkscheinnummer),&((*wagen).zeit),&((*wagen).Dauerparker),&((*wagen).bezahlt),&((*wagen).Parkplatztyp),&((*wagen).ausgefahren),&((*wagen).Kennzeichen));
        if(((*wagen).Parkscheinnummer) == Parkscheinnummer_tmp)
        {
            ((*wagen).bezahlt) = 'j';
            fprintf(CSV,"%i,%i,%i,%c,%c,%c,%c,%s",((*wagen).Kundennummer),((*wagen).Parkscheinnummer),((*wagen).zeit),((*wagen).Dauerparker),((*wagen).bezahlt),((*wagen).Parkplatztyp),((*wagen).ausgefahren),((*wagen).Kennzeichen));
        }
    }while(fscanf(CSV,"%i,%i,%i,%c,%c,%c,%c,%s\n",&((*wagen).Kundennummer),&((*wagen).Parkscheinnummer),&((*wagen).zeit),&((*wagen).Dauerparker),&((*wagen).bezahlt),&((*wagen).Parkplatztyp),&((*wagen).ausgefahren),&((*wagen).Kennzeichen)) != EOF );
    return 0;
};



ich hoffe mir kann jemand weiterhelfen

vielen dank im vorraus!
 
Mich beschleicht das Gefühl, dass du dir nur jeden zweiten Datensatz anschaust. Du gehst in die Schleife, liest den ersten und überprüfst die Parkscheinnummer. Den zweiten Datensatz liest du in der Abbruchbedingung und schaust ob du am Ende der Datei bist. Ist das nicht der Fall gehst du wieder in die Schleife und liest den dritten Datensatz. Für den zweiten hast du also nicht getestet ob die Parkscheinnummer mit der eingegebenen übereinstimmt.

Sollte ungefähr so aussehen. (nur hier im Editor zusammengeschoben)
Code:
    while(fscanf(CSV,"%i,%i,%i,%c,%c,%c,%c,%s\n",
        &((*wagen).Kundennummer),
        &((*wagen).Parkscheinnummer),
        &((*wagen).zeit),
        &((*wagen).Dauerparker),
        &((*wagen).bezahlt),
        &((*wagen).Parkplatztyp),
        &((*wagen).ausgefahren),
        &((*wagen).Kennzeichen)) != EOF )
    {
        if(((*wagen).Parkscheinnummer) == Parkscheinnummer_tmp)
        {
            ((*wagen).bezahlt) = 'j';
            fprintf(CSV,"%i,%i,%i,%c,%c,%c,%c,%s",
                ((*wagen).Kundennummer),
                ((*wagen).Parkscheinnummer),
                ((*wagen).zeit,
                ((*wagen).Dauerparker),
                ((*wagen).bezahlt),
                ((*wagen).Parkplatztyp),
                ((*wagen).ausgefahren),
                ((*wagen).Kennzeichen));
        }
    }

Wie du die Datei ändern kannst ohne sie neu zu schreiben weiß ich spontan nicht und bin um die Uhrzeit auch nicht mehr gewillt es herauszufinden, jedoch würde ich dir ans Herz legen dir mal SQLite anzusehen, da es sich bei deiner CSV offenbar um eine Datenbank handelt. Ich glaube das würde dir viel Mühe ersparen, vor allem in Hinblick auf komplexere Funktionen als die Änderung des Bezahlstatus.
 
Sollte ungefähr so aussehen....
genau so habe ichs erst gemacht, dabei hat er die Schleife aber unter keinen Umständen angerührt.

da es sich bei deiner CSV offenbar um eine Datenbank handelt
Ne ist einfach nur ne Datei in der die Daten gespeichert werden sollen...



EDIT:

ich bin mitlerweile bei folgendem:

Code:
    rewind(CSV);
    while(!(feof(CSV)))
    {
        fscanf(CSV,"%i,%i,%i,%c,%c,%c,%c,%s\n",
&((*wagen).Kundennummer),
&((*wagen).Parkscheinnummer),
&((*wagen).zeit),
&((*wagen).Dauerparker),
&((*wagen).bezahlt),
&((*wagen).Parkplatztyp),
&((*wagen).ausgefahren),
&((*wagen).Kennzeichen));
        if(((*wagen).Parkscheinnummer) == Parkscheinnummer_tmp)
        {
            ((*wagen).bezahlt) = 'j';
            fprintf(CSV,"%i,%i,%i,%c,%c,%c,%c,%s",
((*wagen).Kundennummer),
((*wagen).Parkscheinnummer),
((*wagen).zeit),
((*wagen).Dauerparker),
((*wagen).bezahlt),
((*wagen).Parkplatztyp),
((*wagen).ausgefahren),
((*wagen).Kennzeichen));
        }
    }

Das Funkfioniert auch soweit....

Nur das kleine Problem ist irgentetwas stimmt mit der Abbruchbedingung glaube ich nich ....

er liest aus ... schreibt danach den gleichen eintrag wieder herein und ändert auch vorher das richtige in j um ...

aber er schreibt den datensatz in dauerschleife immer wieder rein
solange bis ich das programm mit x schliesse


mit feof(FILEPOINTER) testet man doch auf end of file oder? ....wieso bricht der das nich ab und wieso schreibt der das 5mion mal da rein
 
Zuletzt bearbeitet:
Ok nur falls jemand noch einmal ähnliche Probleme wie ich haben sollte.
Ich habe mitlerweile die Lösung ( zur besseren Trennung von Problen / Fragestellung und Lösung der doppelpost)
Ich hatte mehere Fehler zum einen bin ich davon ausgegangen, dass wenn man einen file mit a öffnet man auch lesen kann, da ja Schreibrechte höher sind als Leserechte.
Dies war offensichtlich ein Trugschluss
zum anderen fehlte meinen fscanf noch der anhang %*[^\n] am ende zwischen den Anführungszeichen
(fscanf liest nur bis vor dem \n ein und bricht bei \n ab so wie ich das mitlerweile verstanden hab und mit dem oben genannten statement kann man das \n überspringen)

der vollständigkeit halber jetzt noch einmal mein code ( nach ein wenig testen sollte dieser möglichst Fehlerfrei sein, falls dem nicht so sein sollte lasse ich mich gerne eines besseren belehren )

Code:
int bezahlen(struct kunde *wagen)
{
    FILE *CSV;          // Deklarieren eines File Pointers namens CSV
    FILE *CSV_tmp;          // Deklarieren eines File Pointers namens CSV_tmp
    CSV = fopen("Parkhaus.csv", "r");   // Öffnen der Datei Parkhaus.csv (welche im gleichen Verzeichnis liegt wie die .exe) mit Änderungsabsicht (wenn die Datei nicht existiert wird Sie hier angelegt)
    if(CSV == NULL)     // Wenn Fehler auftritt ( z.B. benötigte Rechte nicht vorhanden)
    {
        printf("Fehler beim %c \bffnen, Programm wird beendet",OE);    //Ausgabe Fehlermeldung
        exit(0);                                //Programm beenden
    }
    int Parkscheinnummer_tmp;	// Deklarieren der Integer Variablen Parkscheinnummer_tmp
    printf("Geben Sie ihre Parkscheinnummer ein und dr%c \bcken Sie Enter.\n",ue);	//Aufforderung an den User seine Parkscheinnummer einzugeben
    scanf("%i",&Parkscheinnummer_tmp);		// Abfangen der Usereingabe und abspeichern dieser in die Integer Variable Parkscheinnummer_tmp
    fflush(stdin);		//Tastaturpuffer leeren
    rewind(CSV);		// den Positionszeiger von CSV auf Dateianfang setzten
    while((fscanf(CSV,"%i,%i,%i,%c,%c,%c,%c,%s%*[^\n]",&((*wagen).Kundennummer),&((*wagen).Parkscheinnummer),&((*wagen).zeit),&((*wagen).Dauerparker),&((*wagen).bezahlt),&((*wagen).Parkplatztyp),&((*wagen).ausgefahren),&((*wagen).Kennzeichen))) != EOF)	// Kopfgesteuerte Schleife in der immer die nächste Zeile in die Struktur gelesen wird und dies auf ungleich End Of File Flag getestet wird
    {
        if(((*wagen).Parkscheinnummer) == Parkscheinnummer_tmp)		// Wenn die Integer Variable Parkscheinnummer des aktuellen Datensatzes gleich dem Wert in der Integer Variablen Parkscheinnummer_tmp ist dann:
        {
            ((*wagen).bezahlt) = 'j';	// Die Character Variable bezahlt des aktuellen Datensatzes auf j setzten
            CSV_tmp = fopen("Parkhaus_tmp.csv", "w");   // Öfnnen der Datei Parkhaus_tmp mit Lösch und Änderungsabsicht ( wenn die Datei nicht existiert wird sie hier angelegt)
            fprintf(CSV_tmp,"\n%d,%d,%d,%c,%c,%c,%c,%s",((*wagen).Kundennummer),((*wagen).Parkscheinnummer),((*wagen).zeit),((*wagen).Dauerparker),((*wagen).bezahlt),((*wagen).Parkplatztyp),((*wagen).ausgefahren),((*wagen).Kennzeichen));   // aktuellen Datensatz in temporäre csv datei schreiben
            while((fscanf(CSV,"%i,%i,%i,%c,%c,%c,%c,%s%*[^\n]",&((*wagen).Kundennummer),&((*wagen).Parkscheinnummer),&((*wagen).zeit),&((*wagen).Dauerparker),&((*wagen).bezahlt),&((*wagen).Parkplatztyp),&((*wagen).ausgefahren),&((*wagen).Kennzeichen))) != EOF)    // Kopfgesteuerte schleife (Parkhaus.csv Zeilenweise lesen und in Struktur schreiben) / Schleife läuft bis Statement End of Flag zurückliefert
            {
                if(((*wagen).Parkscheinnummer) != Parkscheinnummer_tmp)     // Wenn Die Parkscheinnummer der Usereingabe nicht mit der des aktuellen Datensatzes übereinstimmt dann:
                {
                    fprintf(CSV_tmp,"\n%d,%d,%d,%c,%c,%c,%c,%s",((*wagen).Kundennummer),((*wagen).Parkscheinnummer),((*wagen).zeit),((*wagen).Dauerparker),((*wagen).bezahlt),((*wagen).Parkplatztyp),((*wagen).ausgefahren),((*wagen).Kennzeichen));   // aktuellen Datensatz in temporäre csv datei schreiben
                }
            }
            fclose(CSV);		// Filepointer namens CSV freigeben / Datei wieder schliessen
            fclose(CSV_tmp);    // Filepointer namens CSV_tmp freigeben / Datei wieder schliessen
            CSV = fopen("Parkhaus.csv", "w");   // Datei Parkhaus.csv öffnen mit einer Lösch und Änderungsabsicht   ( wenn die Datei nicht existiert wird sie hier angelegt )
            CSV_tmp = fopen("Parkhaus_tmp.csv", "r");   // Datei Parkhaus.csv öffnen mit einer Leseabsicht
            while((fscanf(CSV_tmp,"%i,%i,%i,%c,%c,%c,%c,%s%*[^\n]",&((*wagen).Kundennummer),&((*wagen).Parkscheinnummer),&((*wagen).zeit),&((*wagen).Dauerparker),&((*wagen).bezahlt),&((*wagen).Parkplatztyp),&((*wagen).ausgefahren),&((*wagen).Kennzeichen))) != EOF)    // Kopfgesteuerte schleife (Parkhaus.csv Zeilenweise lesen und in Struktur schreiben) / Schleife läuft bis Statement End of Flag zurückliefert
            {
                    fprintf(CSV,"\n%d,%d,%d,%c,%c,%c,%c,%s",((*wagen).Kundennummer),((*wagen).Parkscheinnummer),((*wagen).zeit),((*wagen).Dauerparker),((*wagen).bezahlt),((*wagen).Parkplatztyp),((*wagen).ausgefahren),((*wagen).Kennzeichen));   // aktuellen Datensatz in temporäre csv datei schreiben
            }
            fclose(CSV);    // Filepointer namens CSV freigeben / Datei wieder schliessen
            fclose(CSV_tmp);    // Filepointer namens CSV_tmp freigeben / Datei wieder schliessen
        }
    }
    return 0;		// Funktionsende
};
 
Schön, dass du dein Problem lösen konntest. Nun würde ich dir diesen Artikel ans Herz legen.

Falls du das nicht für den Lerneffekt betrieben hast, solltest du dich auch mal nach existierenden Libs umsehen, denn die haben es meistens an sich, dass viele Probleme, an die du beim neu Erfinden des Rads gar nicht denkst, schon gelöst sind.
 
Kleiner Hinweis zur Syntax:

Anstatt
Code:
(*pointer).struct_variable
kannst du auch die Abkürzung
Code:
pointer->struct_variable
benutzen. Das macht den Code um einiges lesbarer ;)
 
Zurück
Oben