Aktuelles Datum in Datei speichern.
-
Hallo zusammen,
für mein Fernstudium muss ich ein kleines Programm schreiben, in dem u.a. Kundendaten eingelesen werden sollen. Dafür habe ich bis jetzt folgenden Code:
void kunde_erfassen() { FILE *datei; KUNDE neu_kunde; long zeit; struct tm *datum; int variante_datum; int k_id=0; //aktuelle Kundennummer holen //k_id = akt_id("kunden.txt"); neu_kunde.k_id=k_id; printf("\nBitte Daten zum Kunden Nummer %d eingeben!", k_id); //Datum auswählen lassen printf("\nAktuelles Datum fuer Vertragsbeginn? (1=ja, sonst manuelle Eingabe) ");scanf_s("%d", &variante_datum); //aktuelles Datum als Vertragsdatum if(variante_datum==1) { time(&zeit); //aktuelle Zeit datum=localtime(&zeit); // konvertieren neu_kunde.abschluss.jahr=datum->tm_year; neu_kunde.abschluss.monat=datum->tm_mon; neu_kunde.abschluss.tag=datum->tm_mday; } else //Datum manuell einlesen { printf("\nBitte Tag eingeben:");scanf_s("%d",&neu_kunde.abschluss.tag); printf("Bitte Monat eingeben:");scanf_s("%d",&neu_kunde.abschluss.monat); printf("Bitte Jahr eingeben:");scanf_s("%d",&neu_kunde.abschluss.jahr); } //restliche Daten erfassen printf("\nWeitere Kundendaten"); fflush(stdin); printf("\nName:");gets_s(neu_kunde.name,sizeof(neu_kunde.name)); printf("Vorname:");gets_s(neu_kunde.vorname,sizeof(neu_kunde.vorname)); printf("Strasse:");gets_s(neu_kunde.anschrift.strasse,sizeof(neu_kunde.anschrift.strasse)); printf("Hausnummer:");scanf_s("%d",&neu_kunde.anschrift.hausnummer); fflush(stdin); printf("PLZ:");gets_s(neu_kunde.anschrift.plz,sizeof(neu_kunde.anschrift.plz)); printf("Ort:");gets_s(neu_kunde.anschrift.ort,sizeof(neu_kunde.anschrift.ort)); //Datei öffnen, Artikel einschreiben, Datei schließen datei=fopen("kunden.txt","a+"); fprintf(datei,"%d;%s;%s;%s;%d;%d;%s;%d.%d.%d",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.abschluss.tag,neu_kunde.abschluss.monat,neu_kunde.abschluss.jahr); fclose(datei); }
Jetzt zeigt mir jedoch nach Ablauf der Funktion der Debugger immer den Fehler:
"Stack arround Variable "zeit" corrupted." Das Jahr in der Textdatei passt dann auch nicht mehr ganz. Hat jemand eine Idee? Kann ich das Datum ggf. auch einfacher speichern?Danke für Eure Hilfe!
-
Die Funktion
time()
erwartet einen Zeiger auf eine Variable vom Typtime_t
.
Du hastlong
.
-
Vielen Dank für die rasche Antwort!
Also ich habe jetzt die Variable zeit als
t_time *zeit;
deklariert.
Wenn ich jetzt
time(zeit);
aufrufe, erhalte ich die fehlermeldung das die Variable nicht initialisiert ist.
Ich glaube ich kann die Funktion noch nicht ganz nachvollziehen :-\
-
So ein Zeiger sollte auch auf etwas zeigen.
-
Ersetze in deinem Code oben das long durch time_t
Kein Zeiger.
Dann muss aber der Adressoperator & wieder beim Aufruf von time stehen.
-
Wunderbar, jetzt klappt es
Musste nurnoch das Datum etwas formatieren.
Gibt es eigentlich eine Möglichkeit, den Datensatz mit fprintf so in der Datei zu speichern, dass ich ihn auch Satzweise mit fscanf wieder auslesen kann?
Ich hab ja jetzt jedes Datum mit ; getrennt, aber beim einlesen liest er dieses wieder mit ein :-\ Lieber wäre es mir, wenn er mit fscanf das ganze so ein liest, das ich es direkt in den Variablen bzw. in der Struktur abspeichern kann. Versteht ihr was ich meine?
€: Ich hab es jetzt gefunden
Man muss den statt %s einfach %[^';'] einlesen. Wobei ; mit dem entsprechenden Trennzeichen ersetzt werden muss. Aber das wisst ihr sich schon
-
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
oderdd.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
stattlong
genommen hast.
Daraus kann man schliessen, dass die beiden Typen nicht gleich sind.Jetzt versuchst du wieder
time_t
mitlong
abzubilden (%ld beifprintf
undfscanf
)
Siehe http://de.wikipedia.org/wiki/Unixtime#Jahr-2038-Problemtime_t
war mal 32-Bit. Was auf den meisten Systemen auch fuerlong
gilt. (Auf Linux 64-Bit Systemen istlong
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 :-\
-
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