Aktuelles Datum in Datei speichern.


  • Mod

    edit: Hier stand Mist



  • Dann zeig doch mal, wie du die Daten wieder einliest.



  • Also ich speichere die Datensätze wie folgt:

    datei=fopen(f_dat,"a+");
    fprintf(datei,"%d;%s;%s;%s;%d;%d;%d;%d\n",neu_kfz.kfz_id,neu_kfz.kennzeichen,neu_kfz.hersteller,neu_kfz.kfz_typ,neu_kfz.kw,neu_kfz.anschaffung.tag,neu_kfz.anschaffung.monat+1,neu_kfz.anschaffung.jahr+1900);
    fclose(datei);
    

    und lese sie jetzt mit

    while(fscanf(dat,"%d;%[^';'];%[^';'];%[^';'];%d;%d;%d;%d\n",
    				&kfz.kfz_id, kfz.kennzeichen, kfz.hersteller, kfz.kfz_typ, &kfz.kw, &kfz.anschaffung.tag, &kfz.anschaffung.monat, &kfz.anschaffung.jahr)!=EOF)
    

    Das funktioniert jetzt ganz gut.

    Ich stehe nun aber vor einem neuen Problem 🙂

    Ich muss pro Kunde bzw. pro Fahrzeug eine laufende ID vergeben. Um diese zu ermitteln war mein Plan, in einer Hilfsfunktion einfach jede Zeile zu lesen und eine Laufvariable hochzählen zu lassen:

    int akt_id(char datei[15])
    {
    	FILE *dat;
    	char hilf[90];
    	int i=0;
    
    	if(dat=fopen(datei,"r")!=NULL)
    		{
    			while(fscanf(dat,"%s", hilf)!=EOF)
    				i++;
    			fclose(dat);
    	}
    	else
    		printf("FEHLER! DATEI NICHT GEFUNDEN!");
    
    	return i;
    }
    

    Er bricht jedoch immer bei der while-Bedingung ab. Ich weiß nicht ob ich das so schreiben kann, aber ich will ja im Prinzip nur die Zeilen/Sätze durchspringen, ohne diese zu speichern.



  • radiac schrieb:

    Man muss den statt %s einfach %[^';'] einlesen.

    Da sind die ' zuviel.

    Das Datum solltest du ruhig in einem genormten Format ablegen: yyyy-mm-dd oder dd.mm.yyyy
    Dann ist das gesammte Datum durch ein ; abgetrennt.

    Eine Hausnummer kann auch 10a sein (also ein String).

    radiac schrieb:

    Er bricht jedoch immer bei der while-Bedingung ab.

    Wo denn sonst?

    Warum ermittelst du das nicht einfach beim einlesen? Dann kannst du die ID auch gleich mit in der struct ablegen.



  • Naja, ich will ja, wenn ich einen neuen Datensatz hinzufüge, die letztmögliche ID nehmen. Die muss ich ja irgendwie rausbekommen, daher die Hilfsfunktion. Mit abbrechen meine ich, dass während der Laufzeit ein Zugriffsfehler entsteht. Hab jedoch im Moment keine Ahnung warum :-\

    €: Also das hab ich jetzt gelöst, es lag an dem Vergleich der for der While-Bedingung kommt.

    Aber mit dem Datum hab ich jetzt noch Probleme. Du hast mich auf eine gute Idee gerbacht. Ich muss später noch mit dem Datum rechnen, daher wollte ich es in der Textdatei möglichst einfach ablegen.

    Meine Idee war, das Datum direkt mittels %dl im time_t Format in der Datei zu speichern und später entsprechend wieder auszulesen. Leider klappt das auslesen überhaupt garnicht 😞

    Wenn ich es mit

    fprintf(datei,"%d;%s;%s;%s;%s;%s;%s;%ld\n",neu_kunde.k_id,neu_kunde.name,neu_kunde.vorname,neu_kunde.anschrift.strasse,neu_kunde.anschrift.hausnummer,neu_kunde.anschrift.plz,neu_kunde.anschrift.ort, neu_kunde.vertrag_beginn);;
    

    speichere und später mit

    while(fscanf(dat,"%d;%[^';'];%[^';'];%[^';'];%[^';'];%[^';'];%[^';'];%ld\n",
    				&kunde.k_id,kunde.name,kunde.vorname,kunde.anschrift.strasse,kunde.anschrift.hausnummer,kunde.anschrift.plz,kunde.anschrift.ort,&kunde.vertrag_beginn)!=EOF)
    

    wieder einlese, erhalte ich immer Zugriffsfehler beim umwandeln mittels localtime.

    datum=localtime(&kunde.vertrag_beginn);
    

    Dabei ist kunde.vertag_beginn vom typ time_t.



  • Deine urspruengliches Problem konntest du dadurch beheben, dass du fuer zeit time_t statt long genommen hast.
    Daraus kann man schliessen, dass die beiden Typen nicht gleich sind.

    Jetzt versuchst du wieder time_t mit long abzubilden (%ld bei fprintf und fscanf )
    Siehe http://de.wikipedia.org/wiki/Unixtime#Jahr-2038-Problem

    time_t war mal 32-Bit. Was auf den meisten Systemen auch fuer long gilt. (Auf Linux 64-Bit Systemen ist long z.B. 64-Bit breit)

    Du kannst die Zeit erstmal in eine temporaere Variable vom Typ long long ablegen. Und danach an kunde.vertag_beginn zuweisen.



  • Nun, das Problem ist eigentlich folgendes:

    Das speichern in der Datei funktioniert, es wird also der Wert an Sekunden abgelegt. Wenn ich aber mit fscanf und der Formatspezifikation %ld das ganze wieder vertrags_beginn zuweisen will (jetzt geändert in long long), erhält er nicht diesen Sekundenwert, sondern den untersten Wert. Als ob der Puffer also überläuft.

    €: Hinzu kommt jetzt noch folgendes Problem: Ich will beim erfassen des Kunden freistellen, ob das aktuelle Datum (also mittels time() ) oder ein manuelles Datum eingegeben werden soll. Im Falle der manuellen Eingabe will ich Tag, Monat und Jahr erfassen (in struct tm datum) erfassen und anschließend in time_t umwandeln. Allerdings erhalte ich beim umwandeln stets -1, also kann nicht umgewandelt werden. Gibt es da eine andere Methode? Offensichtlich fehlen ja in der struct tm einige Parameter...

    Ich bin am verzweifeln 😃



  • Hi,

    das mit dem Datum habe ich jetzt gelöst, aber ich hab nun ein neues Problem. Bei dem Code

    FILE *datei;
    KUNDE neu_kunde;
    
    (.....)
    
    datei=fopen(k_dat, "a+");
    	if(datei=NULL)
    		return;
    
    fprintf(datei,"%d;%s;%s;%s;%s;%s;%s;%d.%d.%d\n", neu_kunde.k_id, neu_kunde.name, neu_kunde.vorname, neu_kunde.anschrift.strasse, neu_kunde.anschrift.hausnummer, neu_kunde.anschrift.plz, neu_kunde.anschrift.ort, neu_kunde.vertrag_beginn.tm_mday, neu_kunde.vertrag_beginn.tm_mon, neu_kunde.vertrag_beginn.tm_year);
    
    fclose(datei);
    

    erhalte ich ständige eine Exception, weil fprintf wohl einen NULL string liefert. So richtig erklären kann ich mir das aber nicht :-\


  • Mod

    Was für eine Exception? Wieso meinst du, dass fprintf einen Nullstring "liefert"? fprintf "liefert" nur die Zahl der erfolgreich geschriebenen Elemente, das kann keine Exception auslösen. Wohl eher, dass du einen Null oder ungültigen zeiger an fprintf lieferst, wo fprintf etwas gültiges erwartet. Wie wird denn neu_kunde gefüllt?
    Bei Laufzeitfehlern daher bitte vollständiges Minimalbeispiel liefern!
    http://www.c-plusplus.net/forum/304133



  • if(datei=NULL)
    

    setzt datei auf NULL, was falsch ist.



  • Mh, also ich hab jetzt fprintf_s durch fprintf ersetzt und da funktioniert es seltsamerweise. So richtig komme ich damit aber nicht voran. Außerdem erhalte ich jetzt eine Exception bei der fclose Anweiseung. Es wird aber alles ordentlich in die Datei geschrieben. Ich steig einfach nicht dahinter :-\



  • Falscher weg.
    Bau mal ein paar Testausgaben im Code ein:

    datei=fopen(k_dat, "a+");
    printf("datei vor  if = %p\n", datei);
        if(datei=NULL)
            return;
    printf("datei nach if = %p\n", datei);
    

    fällt dir etwas auf?
    (Der Compiler sollte auch eine Warnung ausgeben)



  • Ich verstehe was du sagen willst, in der If-Anweisung erfolgt eine Zuweisung statt einem Vergleich. Das habe ich aber schon behoben. Der Code der Funktion sieht insgesamt wiefolgt aus:

    void kunde_erfassen()
    {
    	FILE *datei;
    	KUNDE neu_kunde;
    	struct tm datum;
    	time_t zeit;
    	int variante_datum;
    
    	//aktuelle Kundennummer holen
    	neu_kunde.k_id=akt_id(k_dat);
    
    	printf("\nBitte Daten zum Kunden Nummer %d eingeben!", neu_kunde.k_id);
    
    	//Hier werden verschiedene Kundendaten erfasst.
    
    	//Datei öffnen, Kunden einschreiben, Datei schließen
    	fopen_s(&datei, k_dat,"a+");
    
    	fprintf(datei,"%d;%s;%s;%s;%s;%s;%s;%0d.%0d.%0d;\n", 
    		neu_kunde.k_id, neu_kunde.name, neu_kunde.vorname, neu_kunde.anschrift.strasse, neu_kunde.anschrift.hausnummer, neu_kunde.anschrift.plz, 
    		neu_kunde.anschrift.ort, neu_kunde.vertrag_beginn.tm_mday, neu_kunde.vertrag_beginn.tm_mon+1, neu_kunde.vertrag_beginn.tm_year+1900);
    
    	fclose(datei);
    }
    

    In dieser Funktion wird ja

    neu_kunde.k_id=akt_id(k_dat);
    

    aufgerufen. Diese Funktion wiederrum sieht wiefolgt aus:

    int akt_id(char datei[15])
    {
    	FILE *dat;
    	int i=1;
    
    	fopen_s(&dat, datei,"r");
    
    	while(fscanf(dat,"%s")!=EOF)
    				i++;
    
    	fclose(dat);
    
    	return i;
    }
    

    In dieser Hilfsfunktion wird die Datei geöffnet, die Anzahl der Zeilen ausgelesen und dann wieder geschlossen. Das funktioniert einwandfrei. In der eigentlichen Funktion wird auch der entsprechende Datensatz in die Datei geschrieben, beim schließen (fclose) kommt allerdings eine Fehlermeldung:

    Unbehandelte Ausnahme bei 0x3b657373 in Einsendearbeit.exe: 0xC0000005: Access violation.

    Der Zeiger hat nach dem öffnen und vor dem schließen die gleiche Adresse, das habe ich schon überprüft.



  • Ich hab jetzt übrigens festgestellt, dass das Programm nur dann bei fclose abstürzt, wenn schon etwas in der Datei steht. Wenn Sie leer ist passiert nichts und alles funktioniert bestens 😕



  • Mittlerweile habe ich herausgefunden, dass es nicht an fclose liegt. Das Programm stürzt beim Ende der function ab. Also wenn er wieder zurück in die Main soll. Dort kommt er jedoch nie an, zumindest werde keine Haltepunkte die direkt nach dem Funtkionsaufruf gesetzt sind erreicht.

    Hat jemand eine Idee? Muss mann Strukturen usw. am Funktionsende auf NULL setzen?!


  • Mod

    Erkär doch mal, wie fscanf funktioniert.



  • Das kann ich jetzt nicht ganz nachvollziehen 🙂

    Mein fscanf schreibt wie gesagt in die mitgegebene Datei einen String mit Formatspezifikationen. Die Anzahl und Typen der Spezifikationen stimmen mit den mitgegebenen Parametern ein. Der Zeiger auf die Datei passt auch und in der Datei wird alles richtig geschrieben. Beim fclose kommt es ja auch nicht zu fehlern, wie ich mittlerweile festgestellt habe.

    Oder übersehe ich da was? Bin wie gesagt ein absoluter Neuling in C.



  • radiac schrieb:

    Mein fscanf schreibt wie gesagt in die mitgegebene Datei einen String mit Formatspezifikationen. Die Anzahl und Typen der Spezifikationen stimmen mit den mitgegebenen Parametern ein. Der Zeiger auf die Datei passt auch und in der Datei wird alles richtig geschrieben. Beim fclose kommt es ja auch nicht zu fehlern, wie ich mittlerweile festgestellt habe.

    Oder übersehe ich da was? Bin wie gesagt ein absoluter Neuling in C.

    Der Prototyp von fscanf sieht so aus: int fscanf ( FILE * stream, const char * format, ... );

    Dabei stehen die ... für eine variable Anzahl von Parametern.

    Den Typ und die Anzahl der Paramter ermittelt fscanf aus den Formatspecifieren in dem Formatstring. Für jeden Formatspecifier muss also auch Parameter angegeben sein.

    Wieviel Formatspecifier hast du?

    Vielleicht verstehst du dann auch die Warnung vom Compiler.
    Bzw. schaltest diese ein und beachtest sie auch.



  • Soweit ich es überblicken kann stimmen Format und Anzahl der Parameter überein. Entdeckt du da bei mir einen Fehler?

    Müsste dann nicht auch der Fehler bei der fprintf-Anweisung auftauchen? Oder hab ich hier einen Denkfehler?

    €: Ich hab es übrigens schon mit einer einfach Anweisung fprintf("TEST"); probiert, da erhalte ich denselben Fehler. Ich vermute also, dass es nicht an dieser Anweisung liegt.

    Wie gesagt, auch das flcose ist nicht der Fehler, wie zuerst von mir vermutet. Erst bei Ende der Funktion tritt der Fehler auf, unabhängig davon, welche Anweisungen ich nach fclose noch hinzufüge.



  • radiac schrieb:

    while(fscanf(dat,"%s")!=EOF)
    

    radiac schrieb:

    Soweit ich es überblicken kann stimmen Format und Anzahl der Parameter überein.

    Wo werden die Daten für das %s abgespeichert?


Anmelden zum Antworten