Problem mit fwrite()



  • Ich habe folgendes problem mit diesem teil meines programmes, ich kann die daten nicht in die datei zurückschreiben und ich weiß nicht warum, er holt mir den datensatz aus der datei (wurde binär hineingeschrieben) und ich kann diesen auch ändern, jedoch gibt er mir dann den If-zweig von If(!fwrite(...)) aus und ich weiß einfach nicht warum, wäre für eine hilfe dankbar

    #define GROESSE sizeof(BUCH)
    
    struct DATE
    {
    	int tag;
    	int monat;
    	int jahr;
    };
    struct PERSON
    {
    	char vorname[15];
    	char nachname[15];
    	DATE gebdat;
    };
    struct BUCH
    {
    	char titel[25];
    	PERSON Autor;
    	char verlag[25];
    	char isbn[15];
    	float preis;
    	bool geloescht;
    };
    
    void buch_daten_aendern(char datenbankname[])
    {
    	FILE *datei;
    	BUCH *b;
    	long datensaetze_in_datei;
    	char auswahl;
    	char modus[] = "r+b";
    	char titel[25];
    	int gleich;
    
    	printf("\nBitte den Titel (maximal 25 Zeichen) eingeben: ");
    	fflush(stdin);
    	scanf("%25s", &titel);
    
    	datei = datei_oeffnen(datenbankname, modus); //Öffnen der datei, mit dem "datenbankamen"
    	datensaetze_in_datei = datei_groesse_festlegen(datei); //Festlegen der Anzahl der datensätze die in der geöffneten datei stehen (datensätze vom typ BUCH)
    	b = (BUCH*)malloc(datensaetze_in_datei*GROESSE); //Speicher allozieren für genau die anzahl der Datensätze die in der Datei stehen
    	rewind(datei); //Filepointer zurück stellen auf Anfang des Files
    	if(b) //Wenn speicher alloziert wurde
    	{
    		rewind(datei); //Sicherheitshalber nochmal an den Datei anfang gehen
    		fread(b, GROESSE, datensaetze_in_datei, datei);//Aus der Datei die Anzahl "datensaetze_in_datei" in den Speicher schreiben
    		for(long datensatz_nummer = 0; datensatz_nummer<datensaetze_in_datei;datensatz_nummer++) //Solange datensätze im Speicher stehen
    		{
    			gleich = strcmp(b[datensatz_nummer].titel, titel); //Wenn gleich 0 ist, dann sind die strings ident, vergleichen der Titel
    			if(gleich == 0)
    			{
    				printf("\nFolgender Datensatz wurde gefunden:\n");
    				ausgabe_buch_bildschirm(b[datensatz_nummer]);
    				printf("Wollen Sie diesen  Datensatz ändern (J)a oder (N)ein: ");
    				auswahl = toupper(getch());
    				if(auswahl == 'J')
    				{
    					printf("\nBitte geben Sie folgende Daten neu ein:\n\n");
    					datensatz_eingeben(b[datensatz_nummer]);
    				}
    			}
    		}
    		if(!fwrite(&b, GROESSE, datensaetze_in_datei, datei))
    	 	{
    			printf("Die Datensaetze konnte nicht in die Datein eingetragen werden\n");
    			getch();
    		}
    		else
    		{
    			printf("\nDie Datensaetze wurden erfolgreich in die Datei eingetragen!");
    			getch();
    		}
    		free(b);
    	}
    	else
    	{
    		if(datensaetze_in_datei == 0)
    		{
    			printf("\nEs sind keine Datensaetze vorhanden");
    		}
    		else
    		{
    			printf("\nEs ist nicht genügend Speicher vorhanden");
    		}
    	}
    	auswahl = 'J';
    	fclose(datei);
    }
    long datei_groesse_festlegen(FILE *datei)
    {
    	fseek(datei,0L,SEEK_END);//Dateipointer geht auf das Ende der Datei
    	return ftell(datei)/GROESSE; //Anzahl der Datensätze zurückgeben
    }
    FILE *datei_oeffnen(char datenbankname[],char modus[])
    {
    	return fopen(datenbankname, modus); //öffnent eine Datei im "modus"
    }
    


  • So weit ich das Überblicke, öffnest du die Datei im Modus

    char modus[] = "r+b";
    

    Also Read-Only Binär.



  • SeppSchrot schrieb:

    So weit ich das Überblicke, öffnest du die Datei im Modus

    char modus[] = "r+b";
    

    Also Read-Only Binär.

    r+b ist lese und schreibe modus, hab ich extra nach geschaut

    rb ist read only modus

    leider ist das nicht das problem



  • Was ist GROESSE??

    In dem Fall solltest du lieber mit sizeof(struct BUCH) arbeiten, denn du weißt sicherlich nicht genau, wie groß deine Structur in Wirklichkeit wird. Oder ist GROESSE ein Makro, dass genau das enthält?

    Warum fwrite() immer den Status Fehler zurückliefert, beantworte ich dir mit einer Frage: Was ist in einem Zeiger gespeichert?



  • AJ schrieb:

    Was ist GROESSE??

    In dem Fall solltest du lieber mit sizeof(struct BUCH) arbeiten, denn du weißt sicherlich nicht genau, wie groß deine Structur in Wirklichkeit wird. Oder ist GROESSE ein Makro, dass genau das enthält?

    Warum fwrite() immer den Status Fehler zurückliefert, beantworte ich dir mit einer Frage: Was ist in einem Zeiger gespeichert?

    GROESSE ist folgendermassen angegeben, hab ich vergessen hinzuschreiben 😉

    #define GROESSE sizeof(BUCH)
    

    so ist GROESSE festgelegt,

    im Filepointer zeigt auf die Datei die geöffnet wird, und zwar auf den Anfang der Datei

    Edit: hab oben nochmal alles besser ausdokumentiert



  • @Hirogen
    Weißt du jetzt woran es liegt (fwrite())? Oder muss ich es dir noch erklären?



  • AJ schrieb:

    @Hirogen
    Weißt du jetzt woran es liegt (fwrite())? Oder muss ich es dir noch erklären?

    Es liegt definitiv nicht daran, hab auch schon meine programmier prof gefragt und der meint das es soweit ok ist, jedoch schreibt er mir einfach nicht in die datei, es muss an irgendwas anderem liegen.

    Wenn ich einen breakpoint lege und das programm dort kurzzeitig abbricht (.net) kann ich mir den inhalt der variablen ansehen, und wenn ich mir den Inhalt des pointer b (BUCH *b) anseheh, steht dort irgnedwas kryptisches und dann immmer wieder "Fehlerhafter Pointer" könnte es damit was zu tun haben

    aber eine erklärung wie du es meinst wäre sicherlich hilfreich



  • Lass mal das & beim ersten Parameter weg.



  • MFK schrieb:

    Lass mal das & beim ersten Parameter weg.

    das und ist relativ egal, auch das sizeof war nicht schuld es war etwas ganz simples 😞

    [cpp]
    rewind(datei);
    if(!fwrite(&b, GROESSE, datensaetze_in_datei, datei))
    {
    printf("Die Datensaetze konnte nicht in die Datein eingetragen werden\n");
    getch();
    }
    else [/cpp]

    und zwar hat vor dem fwrite() kurzerhand ein rewind(datei) gefehlt, anscheinend hat er die ganze zeit auf EOF gezeigt und somit schreibt er ja nix rein, naja jetzt hat sich das erledigt 😃



  • Das & vor b bei deinem fwrite() gehört trotzdem weg. b ist ein Zeiger und hat damit eine Adresse als Inhalt. fwrite() erwartet eine Adresse, wo die Daten stehen. Hast du überhaupt schon überprüft, ob die Daten in der Datei richtig sind, nachdem du sie reingeschrieben hast?



  • AJ schrieb:

    Das & vor b bei deinem fwrite() gehört trotzdem weg. b ist ein Zeiger und hat damit eine Adresse als Inhalt. fwrite() erwartet eine Adresse, wo die Daten stehen. Hast du überhaupt schon überprüft, ob die Daten in der Datei richtig sind, nachdem du sie reingeschrieben hast?

    das & ist dem .net Studio relativ egal, es interessiert sich nicht dafür, zum einen deshalb weil eine Adresse drin steht, und somit so und so eine Adresse übergeben wird, richtigkeits halber gehört aber das & weg und das hab ich auch getan.

    Sowohl wenn das & weg ist als auch wenn es dabei ist werden die Daten richtig in die Datei hineingeschrieben.

    nachdem ich das rewind jetzt hinzugefügt habe funktioniert es einwandfrei 😃



  • Hirogen(CD) schrieb:

    das & ist dem .net Studio relativ egal

    Eigentlich nicht; es ja ein unterschied ist ob du die Adresse übergeben willst, die in dem Pointer steht oder die Adresse des Pointers selbst...:)
    Sowas kann eigentlich nicht mal MS bringen ^^



  • Splieth@School schrieb:

    Hirogen(CD) schrieb:

    das & ist dem .net Studio relativ egal

    Eigentlich nicht; es ja ein unterschied ist ob du die Adresse übergeben willst, die in dem Pointer steht oder die Adresse des Pointers selbst...:)
    Sowas kann eigentlich nicht mal MS bringen ^^

    probiers im .net aus, es war meinem .net egal, ob ich &b oder b geschrieben habe.

    Und ich kann mir auch gut vorstellen warum.

    wenn ich &b schreib übergebe ich ja die Adresse mit und wenn ich b schreib übergebe ich auch die Adresse mit da ja "bei einem Pointer immer die Adresse übergeben wird."

    zitat meines C/C++ Prof.



  • Meiner Logik nach dürfte das trotzdem nur zufall sein... Es sei denn der Compiler holt sich den Wert der Adresse die in der Adresse steht, die du übergeben hast (also des Pointers ;)). Ganz vorstellen kann ich mir das aber eher nich; selbst wenn klingt das doch sehr unsicher, ist schließlich MS.
    Prinzipiell kann ich mir das aber nicht so vorstellen, weil der Pointer ja 'ne ganz andere Adresse hat als auf was er zeigt! Sehe ich zumindest so ^^



  • funktioniert unter dem Borland Builder auch



  • Ändert aber nichts an meiner Erklärung... fwrite will die Adresse an der die Daten stehen, nicht die Adresse des Zeigers, der auf diese Daten zeigt! Dessen Adresse liegt ja (ganz) wo anderes :p



  • Splieth@School schrieb:

    Ändert aber nichts an meiner Erklärung... fwrite will die Adresse an der die Daten stehen, nicht die Adresse des Zeigers, der auf diese Daten zeigt! Dessen Adresse liegt ja (ganz) wo anderes :p

    das stimmt schon aber fwrite, wandelt diese daten automatisch um 😉 das meine ich damit, und somit ist es wurscht was ich dem fwrite übergebe.



  • Mag ja sein, dass es einige Compiler so handhaben, was ich ja auch gar net bestreitet habe. Nur kannst du ja nicht Blind davon ausgehen, dass dies bei jedem geschieht und laut Referenzen findet nunmal keine automatische Umwandlung statt; ergo: gleich vernünftig übergeben! 😉



  • Splieth@School schrieb:

    Mag ja sein, dass es einige Compiler so handhaben, was ich ja auch gar net bestreitet habe. Nur kannst du ja nicht Blind davon ausgehen, dass dies bei jedem geschieht und laut Referenzen findet nunmal keine automatische Umwandlung statt; ergo: gleich vernünftig übergeben! 😉

    funktioniert auch beim Borland Turbo C++ 3.xx und der ist schon sehr happig was solche sachen betrifft und auch schon sau alt, insofern kann ich davon ausgehen das jeder NEUE compiler dieses auch automatisch erkennt und sollte er es nicht erkennen muss ich es ändern.



  • Nein, kannst du nicht! Wenn etaws nicht genormt ist kannst du nicht einfach davon ausgehen, dass die "Funktion" bei jedem Compiler implementiert ist! Nur weil ein altes Auto ABS hat kann du ja auch nicht davon ausgehen, dass auch jedes neue über dieses tolle Gimmick verfügt...;) Wenn dein Prof was anderes sagt: erschlagen! 😉


Anmelden zum Antworten