Aktuelles Datum in Datei speichern.



  • 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?


  • Mod

    radiac schrieb:

    Mein fscanf schreibt wie gesagt in die mitgegebene Datei einen String mit Formatspezifikationen.

    Sicher?

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

    Deswegen gebe ich dir ja auch einen Hinweis auf den Fehler. Vielleicht solltest du weniger wild herum experimentieren und stattdessen mal den Hinweisen folgen, die dir gegeben werden? Experimentieren ist ja schön und gut, aber ich zitiere mal:

    c.rackwitz schrieb:

    Wenn du selber Code schreibst, musst du ihn auch verstehen. Code ist kein Haufen von wahllos zusammengeschmissenen Buchstaben und Zeichen, Code ist Logik pur. Du musst genau wissen, warum du wo und welches Zeichen setzt.

    Wenn du bei fscanf nicht genau weißt, wie es funktioniert (oder dir jemand sagt, dass du es nicht weißt, obwohl du selber das anders siehst), dann wäre es vielleicht Zeit für ein bisschen RTFM. Hier findest du Referenzen zu C-Funktionen:
    http://www.cplusplus.com/reference/clibrary/
    http://en.cppreference.com/w/c



  • Ach, jetzt ich erstmal das ich hier ständig fscanf statt fprintf schreibe :-\ Sorry dafür.

    Also das Problem tritt ja nicht bei der Funktion mit fscanf auf. Mir ist klar, das ich mit

    fopen_s(&dat, datei,"r");
    
    	while(fscanf(dat,"%s")!=EOF)
    				i++;
    
    	fclose(dat);
    

    den ausgelesenen String nirgends speichere. Ich verwende diese Funktion nur dafür, um zu ermitteln wieviele Datensätze in der Datei gespeichert sind. Deswegen soll er einfach alle Zeilen durchgehen und eben i hochzählen. Das funktoniert auch problemlos, er beendet diese Hilfsfunktion ohne abzustürzen usw.

    Mein Problem liegt wie gesagt hier:

    [code="c"]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); ---> Das ist die obige Unterfunktion

    printf("\nBitte Daten zum Kunden Nummer %d eingeben!", neu_kunde.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
    localtime_s(&datum, &zeit);
    neu_kunde.vertrag_beginn.tm_year=datum.tm_year;
    neu_kunde.vertrag_beginn.tm_mon=datum.tm_mon;
    neu_kunde.vertrag_beginn.tm_mday=datum.tm_mday;
    }
    else //Datum manuell einlesen
    {
    fflush(stdin);
    printf("\nBitte Tag eingeben (dd):");scanf_s("%d",&neu_kunde.vertrag_beginn.tm_mday);
    printf("Bitte Monat eingeben (mm):");scanf_s("%d",&neu_kunde.vertrag_beginn.tm_mon);
    printf("Bitte Jahr eingeben (yyyy):");scanf_s("%d",&neu_kunde.vertrag_beginn.tm_year);
    }

    //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:");gets_s(neu_kunde.anschrift.hausnummer,sizeof(neu_kunde.anschrift.hausnummer));
    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, Kunden einschreiben, Datei schließen
    fopen_s(&datei, k_dat,"a+");

    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+1, neu_kunde.vertrag_beginn.tm_year+1900);

    fclose(datei);
    printf("Test");
    }[/code]

    Die beiden letzten Anweisungen (fett) werden ausgeführt, auch das "Test" erscheint noch auf der Console. Aber danach bricht das Programm ab. Er kommt auch nicht bis zurück zur Main. Sollte das wirklich an der Unterfunktion oben liegen, in der ich ohne Parameter mitzugeben einfach mittels fscanf die Zeilen durchlaufe? Ich hab das mal mit nem char[90] Parameter probiert --> selber fehler.



  • radiac schrieb:

    Mir ist klar, das ich mit ... (fscanf(dat,"%s") ...
    den ausgelesenen String nirgends speichere.

    Falsch. Der String wird irgendwo gespeichert. fscanf kann nur anhand der Formatspecifier wissen, wieviel Paramter da noch kommen. Und dann müssen die auch da stehen.
    fscanf holst sich die Adresse vom Stack, auch wenn die nicht vom Funktionsaufruf sind. Dieses irgendwo kann bei deinen anderen Daten oder im Programmcode liegen.

    Da ich nur [ code][ /code] sehe, bei zitieren aber der Code auftaucht, hier nochmal. Scheint ein Problem mit den [ b][ /b] Tags zu sein

    radiac schrieb:

    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); // FETT---> Das ist die obige Unterfunktion
    	
    	printf("\nBitte Daten zum Kunden Nummer %d eingeben!", neu_kunde.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
    		localtime_s(&datum, &zeit);
    		neu_kunde.vertrag_beginn.tm_year=datum.tm_year;
    		neu_kunde.vertrag_beginn.tm_mon=datum.tm_mon;
    		neu_kunde.vertrag_beginn.tm_mday=datum.tm_mday;
    	}
    	else //Datum manuell einlesen
    	{
    		fflush(stdin);
    		printf("\nBitte Tag eingeben (dd):");scanf_s("%d",&neu_kunde.vertrag_beginn.tm_mday);
    		printf("Bitte Monat eingeben (mm):");scanf_s("%d",&neu_kunde.vertrag_beginn.tm_mon);
    		printf("Bitte Jahr eingeben (yyyy):");scanf_s("%d",&neu_kunde.vertrag_beginn.tm_year);
    	}
    
    	//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:");gets_s(neu_kunde.anschrift.hausnummer,sizeof(neu_kunde.anschrift.hausnummer));
    	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, Kunden einschreiben, Datei schließen
    	fopen_s(&datei, k_dat,"a+");
    
    	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+1, neu_kunde.vertrag_beginn.tm_year+1900);
    
    	fclose(datei);  //FETT
    printf("Test");         //FETT
    }
    

    Entweder du machst mehr Debugausgaben mit aktuellen Werten und Zeigern oder du probierst mal den Debugger aus.

    Grenze das Problem ein.
    Weise neu_kunde.k_id einen festen Wert zu und verzichte auf akt_id(k_dat);
    Kommentiere einzelne Zeilen oder Blöcke aus. Minimier den Code auf das nötigste, so dass das Problem gerade noch auftritt.



  • Hallo Dirk,

    vielen Dank für deine ständige Hilfe. Ich hab schon versucht das Problem einzugrenzen, hab mir Zeiger usw. ausgeben lassen und die Struktur beim debuggen geprüft, sprich, ob alle Daten da ordentlich drin stehen. Ich komme einfach nicht auf die Ursache. Auch das fest zuweisen der k_id hat noch nix gebracht.

    Da ich die Aufgabe bis zum 5.12 abgeben muss, werd ich den Fehler erstmal hinten anstellen. Ich verliere zuviel Zeit damit den zu beheben und am Ende verliere ich dadurch vielleicht nur einen Punkt. Ist vielleicht der falsche Ehrgeiz, aber ich muss noch 2 komplette Teilaufgaben implementieren, bei denen ich auch noch nicht so recht weiß wie ich das anstellen soll 🙂

    Sollte ich die Ursache gefunden haben, gebe ich euch aber Bescheid!


Anmelden zum Antworten