Problem mit fwrite und Datentypen



  • Hallo,

    wir schreiben in unserer Uebung zur Vorlesung "Informatik fuer Maschinenbauer" zur Zeit einen Vokabeltrainer in C. Das Problem: der Code kompiliert, stuerzt aber beim Ausfuehren der Funktion vokabeleingabe in der Zeile

    fwrite(&vokabeln,sizeof(vokabelsatz),1,datenstrom);
    

    mit einem Segmentation fault ab (gcc-Ausgabe: "program exited with code: 139").

    Wenn ich die Warnings, die gcc beim Kompilieren ausspuckt (uebung11-vokabeltrainer-v3.c:81:3: warning: format ‘%s’ expects type ‘char ’, but argument 2 has type ‘char ()[30]’), richtig verstanden habe, koennte es an einem Problem mit den Datentypen liegen, aber ich habe keine Idee, wie mit diesem Problem umzugehen ist.

    Auch unser Uebungsleiter hat den Fehler leider nicht finden koennen.

    Hier nun der Code:

    #include <stdio.h>
    #include <string.h>
    
    // Uebung 05.07.10
    
    // 1. Vokabeln einlesen
    // 2. Vokabeln vergleichen
    
    // Funktionen
    // Datensaetze editieren
    // Vokabeln abfragen
    
    void vokabelabfrage();
    void vokabeleingabe();
    // int trained = 1;
    
    typedef struct Wort{ // Wort = Variable
    	char lang_one[30]; // Englisch
    	char lang_two[30]; // Deutsch
    	// int trained;
    }vokabelsatz; // vokabelsatz = neuer Datentyp
    
    // Array mit 2 Feldern des neuen Datentyps
    vokabelsatz vokabeln[20]; 
    
    int main()
    {
    
    	int loop=1;
    	char auswahl='0';
    	// Programmschleife, die erst auf Wunsch des Benutzers endet
    
    	while(loop){
    		// Auswahlmenu
    		printf("Bitte geben Sie eine 1 ein, wenn Sie Vokabeln ueben moechten, eine 2 wenn Sie Vokabeln eingeben moechten und 3 zum beenden: \n");
    		scanf("%c",&auswahl);
    		switch(auswahl)
    		{
    		case('1'):
    			printf("Herzlich willkommen bei der Vokabelabfrage!\n");
    			vokabelabfrage();
    			break;
    
    		case('2'):
    			printf("Geben Sie Vokabeln ein:   \n");
    			vokabeleingabe();
    			break;
    
    		case('3'):
    			printf("Das Programm wird nun beendet!\n");
    			loop=0;
    			break;
    
    		default:
    			printf("Fehler: Diese Eingabe ist nicht moeglich! \n");
    			break;
    		}
    	}
    
    }
    int i;
    int n;
    void vokabelabfrage(){
    
    	for(i=1; i<3; i++){
    		printf("Uebersetzen Sie bitte den Begriff:    \n");
    		printf("%s",&vokabeln[i].lang_two);
    		printf("\n");
    		scanf("%s",&vokabeln[i].lang_one);
    
    		if(memcmp(vokabeln[i].lang_one,vokabeln[i].lang_two,n)==0){
    			printf("Richtig! \n");
    			//vokabeln[i].trained = 0;
    		}
    		else{
    			printf("Falsch! \n");
    		}
    		/*for(vokabeln[i].trained = 0;){
    		printf("Diese Vokabeln sollten Sie nochmal ueben: " );
    		printf("%s", vokabeln[i].trained = 0);
    		}*/
    
    	}
    
    }
    
    int i;
    void vokabeleingabe(){	
    
    	// Datenstrom angeben:
    	FILE *datenstrom;
    
    	// und einen Datensatz
    	vokabelsatz vokabeln;
    
    	int loop=1;
    	char c;
    
    	// checken ob Datei lesbar
    	if(datenstrom = fopen("vokabeldatei.txt","ab+")!=NULL)
    	{
    		// schleife um mehrere vokabelsaetze eingeben zu koennen
    		while(loop)
    		{
    			// input aufraeumen:
    			do{c=getchar();}while(c!='\n');
    
    			// abfragen des vokabelsatzes
    			printf("Bitte geben Sie das Wort in Englisch ein: \n");
    			scanf("%s",&vokabeln.lang_one);
    			// printf("%p\n", &vokabeln.lang_one);
    
    			printf("Bitte geben Sie das Wort in Deutsch ein: \n");
    			scanf("%s",&vokabeln.lang_two);
    
    			// vokabeln.trained=0;
    
    			// schreiben der Daten auf Platte:
    			fwrite(&vokabeln,sizeof(vokabelsatz),1,datenstrom);
    
    			//sicherstellen dass alles geschrieben wurde:
    			fflush(datenstrom);
    			do{c=getchar();}while(c!='\n');
    
    			// Abfrage ob noch mehr Datensaetze eingegeben werden sollen
    			printf("Weitere Datensaetze eingeben? n=Nein, alles andere: fortfahren  ");
    			scanf("%c",&c);
    			if(c=='n') loop=0;
    		}
    		// schliessen der Datei
    		fclose(datenstrom);
    	}
    	else{
    		printf("Sie koennen die Datei leider nicht oeffnen!");
    	}
    
    }
    


  • int i;
    int n;
    void vokabelabfrage(){

    globale Variablen, pfui!

    if(memcmp(vokabeln[i].lang_one,vokabeln[i].lang_two,n)==0){

    n ist undefiniert!

    int i;
    void vokabeleingabe(){

    globale Variable, pfui!

    Du solltest dich entscheiden, ob du nun auf das Array indiziert zugreifst, oder nicht!
    vokabeln[i].lang_one

    vokabeln.lang_one

    for(i=1; i<3; i++){

    Arrays beginnen mit 0-Index!

    Prinzipiell arbeiten deine beiden Funktionen IMHO falsch.
    Die Eingabefunktion sollte neue Vokabeln(falls noch nicht vorhanden) in die Datei schreiben und diese dann schließen.
    Die Auswertung sollte diese Datei dann satzweise lesen, auf Gleichheit prüfen und dann die Datei wieder schließen.
    Ein Vokabelnarray brauchst du somit gar nicht und hast somit auch keine Probleme bei der Dimensionierung des Arrays.



  • [quote="Wutz"]

    ...
    Die Eingabefunktion sollte neue Vokabeln(falls noch nicht vorhanden) in die Datei schreiben und diese dann schließen.
    Die Auswertung sollte diese Datei dann satzweise lesen, auf Gleichheit prüfen und dann die Datei wieder schließen.
    ...

    pfui!



  • So z.B. kann es funktionieren.
    Ich nehme die Aufwangsentschädigung eures Übungsleiters gern entgegen 🙂

    typedef struct { // Wort = Variable
        char lang_one[30]; // Englisch
        char lang_two[30]; // Deutsch
        // int trained;
    }vokabelsatz; // vokabelsatz = neuer Datentyp 
    
    const char *deutschFuerEnglisch(const char *dateiname,char *englisch)
    {
    	vokabelsatz paar;
    	FILE *datei=fopen(dateiname,"rb");
    	if(!datei)
    		return 0;
    	while( 1==fread(&paar,sizeof paar,1,datei) )
    		if( !strcmp(paar.lang_one,englisch) )
    			return fclose(datei),strcpy(englisch,paar.lang_two);
    	fclose(datei);
    	return 0;
    }
    
    int addiereVokabelPaar(const char *dateiname,vokabelsatz paar)
    {
    	FILE *datei;
    	if( deutschFuerEnglisch(dateiname,paar.lang_one) )
    		return 0;
    	if( !(datei=fopen(dateiname,"a+b")) )
    		return perror(dateiname),0;
    	return 1==fwrite(&paar,sizeof paar,1,datei) & !fclose(datei);
    }
    
    main()
    {
    	char *d="vokabeln.bin";
    	vokabelsatz p;
    	char c;
    	while(1)
    		switch((c=getchar())=='\n'?getchar():c) {
    		case '1': puts("neu e/d:");scanf("%s",p.lang_one);scanf("%s",p.lang_two);addiereVokabelPaar(d,p);break;
    		case '2': puts("suche e:");scanf("%s",p.lang_one);if(deutschFuerEnglisch(d,p.lang_one)) puts(p.lang_one);break;
    		default: return 0;
    	}
    	return 1;
    }
    

    Als weitere Übungen kannst du mal probieren:
    - Ignorierung Groß-Kleinschreibung
    - Übersetzung andersrum
    - Mehrfach-Übersetzungsalternativen
    - sortierte Komplettliste ausgeben
    - ...


Anmelden zum Antworten