dynamische Liste -> mit fwrite in Datei speichern



  • Hallo Leute,

    ich habe folgendes Problem:

    ich möchte eine dynamisch erzeugte Liste von Strukturen mit fwrite in eine Binärdatei schreiben. Beim Compilieren bekomme ich keine Fehler. Doch wenn ich die Datei wieder in eine dynamisch erzeugte Liste laden will, bekomme ich die eingebenen Daten nicht wieder zurück.

    Ich habe folgenden Code geschrieben:

    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define L_NAME 31
    #define L_STRASSE 31
    #define L_PLZ 7
    #define L_STADT 31
    #define L_TELNR 21
    #define L_DATEINAME 13
    #define CLS system("cls")
    
    typedef struct person
    {
    	char name[L_NAME];
    	char vorname[L_NAME];
    	char strasse[L_STRASSE];
    	char plz[L_PLZ];
    	char stadt[L_STADT];
    	char telnr[L_TELNR];
    	person *next;
    }PERSON;
    
    void anhaengen(char n[], char v[], char s[], char p[], char o[], char t[]);
    void ausgabe();
    void eingabe();
    void loeschen(char wen[]);
    void loeschen_alles();
    void aktualisieren(char nn[]);
    void menue();
    void speichern(char d_name[]);
    void lesen(char d_name[]);
    
    PERSON *first = NULL;
    PERSON *next = NULL;
    
    int main()
    {
    	char dname[L_NAME];
    	FILE *p_datei;
    	char datei_name[L_DATEINAME];
    	char antw = 'n';
    	int auswahl;
    
    //	CLS;
    
    	printf("Geben Sie den Namen der zu bearbeitenden Datei "
    			"ein.\nStandarddatei 'listtel.bin': ");
    	scanf("%12s", datei_name);
    
    	if( (p_datei = fopen(datei_name, "rb")) == NULL)
    	{
    		printf("Die Datei '%s' ist noch nicht vorhanden.\n", datei_name);
    		printf("Das Programm kann hier abgebrochen werden,\n"
    				"Ansonsten wird eine Datei dieses Namens erstellt.\n\n\n");
    		printf("Soll das Programm abgebrochen werdem? (y/n)");
    		fflush(stdin);
    		scanf("%c", & antw);
    		if ((antw == 'y')||(antw == 'Y'))
    			exit(1);
    	}
    
    	else
    	{
    		fclose(p_datei);
    		lesen(datei_name);
    	}
    
    	do
    	{
    		menue();
    		scanf("%d", &auswahl);
    
    		switch(auswahl)
    		{
    			case 1:		fflush(stdin);
    						eingabe();
    						break;
    
    			case 2:		fflush(stdin);
    						printf("Name zum Loeschen: ");
    						fgets(dname, L_NAME, stdin);
    						loeschen(strtok(dname, "\n"));
    						break;
    
    			case 3:		fflush(stdin);
    						loeschen_alles();
    						break;
    
    			case 4:		fflush(stdin);
    						break;
    
    			case 5:		fflush(stdin);
    						ausgabe();
    						break;
    
    			case 6:		fflush(stdin);
    						speichern(datei_name);
    						break;
    
    			case 9:		fflush(stdin);
    						printf("Das Programm wirklich verlassen? (y/n): ");
    						scanf("%c", &antw);
    						break;
    
    			default:	fflush(stdin);
    						printf("Das Programm wirklich verlassen? (y/n): ");
    						scanf("%c", &antw);
    						break;
    		}
    	} while ((antw != 'y') && (antw != 'Y'));
    return 0;
    }
    
    /********************************************************/
    /**********			Funktion Anhaengen		*************/
    /********************************************************/
    /*														*/
    /*	Funktion zur Anhaengen der Daten					*/
    /********************************************************/
    /*														*/
    /* Mit dieser Funktion wird ein Datensatz angehaengt	*/
    /* und geben einen neuem ein n=name, v=vorname,			*/
    /* s=strasse, p=plz, o=stadt, t=telnr					*/
    /********************************************************/
    
    void anhaengen(char n[], char v[], char s[], char p[], char o[], char t[])
    {
    	PERSON *ptr;			//Zeiger zum Zugriff auf die
    							//einzelen Elemente der Struktur
    
    	/*	Wir fragen ab, ob schon ein Element in der Liste gibt.
    		Wir suchen das Element, auf das unser Zeiger *fisrt
    		zeigt. Falls *first immer noch auf NULL zeigt, bekommt
    		*first die Adresse unseres 1. Elements und ist somit
    		der Kopf (Anfang) unserer Liste.	*/
    
    	if(first == NULL)
    	{
    		/*	Wir reservieren Speicherplatz für unsere Struktur bzw.
    			für das erste Element der Liste.	*/
    
    		if((first = (PERSON *) malloc(sizeof(PERSON))) == NULL )
    			fprintf(stderr, "Kein Speicherplatz vorhanden"
    							"fuer das Element first\n");
    		strcpy(first->name, strtok(n,"\n"));
    		strcpy(first->vorname, strtok(v,"\n"));
    		strcpy(first->strasse, strtok(s,"\n"));
    		strcpy(first->plz, strtok(p,"\n"));
    		strcpy(first->stadt, strtok(o,"\n"));
    		strcpy(first->telnr, strtok(t,"\n"));
    
    		/*	Somit haben wir unseren Anfang der Liste. Von nun an
    			zeigt der Zeiger first immer auf das Element vor ihm.
    			Da dies aber jetzt das 1. Element der Liste war, zeigt
    			der Zeiger first auf den Zeiger next. next zeigt am
    			Ende immer wieder NULL	*/
    
    		first->next = NULL;
    	}
    
    	/*	Es scheint schon mindestens ein Element in der Liste
    		vorhanden zu sein, da der Anfang nicht == NULL ist.
    		Jetzt suchen wir so lange nach dem naechsten Element,
    		bis der *next-Zeiger auf NULL zeigt. Somit haben wir
    		das Ende der Liste gefunden und koennen einen neuen
    		Datensatz anhaengen.	*/
    
    	else
    	{
    		ptr = first;			// Wir zeigen nun auf das 1. Element
    		while(ptr->next != NULL)
    			ptr = ptr->next;
    
    		/*	Wir reservieren einen Speicherplatz fuer das letzte
    			Element der Liste und haengen es an.	*/
    
    		if((ptr->next = (PERSON *) malloc(sizeof(PERSON))) == NULL)
    			fprintf(stderr, "Kein Speicherplatz für "
    							"letztes Element\n");
    		ptr = ptr->next;			// Zeiger auf den neuen Speicherplatz
    		strcpy(ptr->name, strtok(n, "\n"));
    		strcpy(ptr->vorname, strtok(v, "\n"));
    		strcpy(ptr->strasse, strtok(s, "\n"));
    		strcpy(first->plz, strtok(p,"\n"));
    		strcpy(ptr->stadt, strtok(o, "\n"));
    		strcpy(ptr->telnr, strtok(t, "\n"));
    
    		/*	Wir terminieren wieder unsere Datenstruktur	*/
    
    		ptr->next = NULL;
    	}
    }
    
    /********************************************************/
    /**********			Funktion Ausgabe		*************/
    /********************************************************/
    /*														*/
    /*	Funktion zur Ausgabe der Daten						*/
    /********************************************************/
    
    void ausgabe()
    {
    	PERSON *ptr;
    	ptr=first;
    	while(ptr != NULL)
    	{
    		printf("\n\nDie Liste beteht aus folgenden Datensatz:\n\n\n");
    		printf("Nachname.........: %s\n",	ptr->name);
    		printf("Vorname..........: %s\n",   ptr->vorname);
    		printf("Strasse..........: %s\n",	ptr->strasse);
    		printf("Postleitzahl.....: %s\n",	ptr->plz);
    		printf("Stadt............: %s\n",   ptr->stadt);
    		printf("Telefonnummer....: %s\n",   ptr->telnr);
    		ptr = ptr->next;
    	}
    }
    
    /********************************************************/
    /**********			Funktion Eingabe		*************/
    /********************************************************/
    /*														*/
    /*	Funktion zur Eingabe der Daten						*/
    /********************************************************/
    
    void eingabe()
    {
    	char nam[L_NAME], vorn[L_NAME], str[L_STRASSE], plz[L_PLZ], ort[L_STADT], tel[L_TELNR];
    
    	printf("Nachname.........: ");
    	fgets(nam, L_NAME, stdin);
    	printf("Vorname..........: ");
    	fgets(vorn, L_NAME, stdin);
    	printf("Strasse..........: ");
    	fgets(str, L_STRASSE, stdin);
    	printf("Postleitzahl.....: ");
    	fgets(plz, L_PLZ, stdin);
    	printf("Stadt............: ");
    	fgets(ort, L_STADT, stdin);
    	printf("Telefonnummer....: ");
    	fgets(tel, L_TELNR, stdin);
    	anhaengen(nam, vorn, str, plz, ort, tel);
    }
    
    /********************************************************/
    /***********		Funktion Löschen		*************/
    /********************************************************/
    /*														*/
    /*	Funktion zum Löschen eines Datensatzes				*/
    /********************************************************/
    
    void loeschen(char wen[])
    {
    	PERSON *ptr, *ptr1;
    
    	/*	Ist überhaupt eine Element in der Liste vorhanden?	*/
    
    	if(first != NULL)
    	{
    		/* Ist unser 1. Element das von uns gesuchte (wen[])?	*/
    
    		if (strcmp(first->name, wen) == 0)
    		{
    			ptr = first->next;
    			free(first);
    			first = ptr;
    		}
    
    		else
    		{
    			/*	Es ist nicht das 1. Element zu löschen.
    				Wir suchen weiter in der Liste, ob das
    				zu löschende Element vorhanden ist	*/
    
    			ptr = first;
    			while(ptr->next != NULL)
    			{
    				ptr1 = ptr->next;
    
    				/*	Ist die Adresse von ptr1
    					der gesuchte Name?		*/
    
    				if(strcmp(ptr1->name, wen) == 0)
    				{
    					/*	Falls ja, dann ...	*/
    
    					ptr->next = ptr1->next;
    					free(ptr1);
    					break;
    				}
    				ptr = ptr1;
    			}			// Ende while
    		}				// Ende else
    	}					// Ende if(first != NULL)
    
    	else
    		printf("Es sind keine Daten zum Loeschen vorhanden!!!\n");
    }
    
    /********************************************************/
    /***********	Funktion Löschen_Alles		*************/
    /********************************************************/
    /*														*/
    /*	Funktion zum Löschen der kompletten Liste			*/
    /********************************************************/
    
    void loeschen_alles()
    {
    	PERSON *ptr, *ptr1;
    
    	/* Ist überhaupt eine Liste zum Löschen vorhanden	*/
    
    	if(first != NULL)
    	{
    		/*	Es ist eine vorhanden ...	*/
    
    		ptr = first->next;
    		while( ptr != NULL)
    		{
    			ptr1 = first->next->next;
    			first->next = ptr1;
    			free(ptr->next);
    			free(ptr);
    			ptr = ptr1;
    		}
    
    		/*	Jetzt löschen wir erst den Anfang der Liste	*/
    
    		free(first->next);
    		free(first);
    		first = NULL;
    		printf("Liste erfolgreich geloescht!!\n");
    	}
    
    	else
    		fprintf(stderr, "Keine Liste zum Loeschen vorhanden!!!\n");
    }
    
    /********************************************************/
    /***********		Funktion Menue			*************/
    /********************************************************/
    /*														*/
    /*	Funktion zur Darstellung des Menues					*/
    /********************************************************/
    
    void menue()
    {
    	//Ueberschrift
    	printf("----------     ADRESSVERZEICHNIS     ----------\n\n\n");
    
    	//Fuer das Menue
    	printf("\t1:    Namen eingeben\n\n");
    	printf("\t2:    Namen loeschen\n\n");
    	printf("\t3:    Komplette Liste loeschen\n\n");
    	printf("\t4:    Namen aktualisieren\n\n");
    	printf("\t5:    Liste anzeigen\n\n");
    	printf("\t6:    Liste speichern\n\n");
    	printf("\t9:    Prgrammabbruch\n\n\n\n\n");
    	printf("Ihre Wahl:		");
    }
    
    /********************************************************/
    /***********		Funktion Speichern		*************/
    /********************************************************/
    /*														*/
    /*	Funktion zum Speichern der Liste in eine Datei		*/
    /********************************************************/
    
    void speichern(char d_name[])
    {
    	FILE *save;
    	PERSON *data = NULL;
    	int zaehler = 0;
    
    	data = first;
    
    	if((data = first) == NULL)
    	{
    		fprintf(stderr, "Liste leer!!");
    		exit(0);
    		getchar();
    	}
    
    	if((save = fopen(d_name, "wb")) == NULL)
    	{
    		fprintf(stderr, "Kann Datei %s nicht oeffnen!", d_name);
    		exit(0);
    	}
    
    	//data = first;
    	/*	Wir schreiben einen Datensatz von Typ PERSON in die angegebene Datei.	*/
    
    	while(data != NULL)
    	{
    	/*	strcpy(first->name, data->name);
    		strcpy(first->vorname, data->vorname);
    		strcpy(first->strasse, data->strasse);
    		strcpy(first->plz, data->plz);
    		strcpy(first->stadt, data->stadt);
    		strcpy(first->telnr, data->telnr);*/
    
    		if(fwrite(&data, sizeof(PERSON), 1, save) != 1)
    		{
    			fprintf(stderr, "Fehler bei fwrite...!!!\n");
    			exit(0);
    		}
    		zaehler++;
    		data = data->next;
    	}
    
    	/*	Wir geben unseren FILE-Zeiger wieder frei.	*/
    
    	fclose(save);
    	fprintf(stderr, "\n\nDatensatze wurden erfolgreich abgespeichert %d.\n", zaehler);
    	getchar();
    }
    
    /********************************************************/
    /***********		Funktion Lesen			*************/
    /********************************************************/
    /*														*/
    /*	Funktion zum Lesen der Liste aus einer Datei		*/
    /********************************************************/
    
    void lesen(char d_name[])
    {
    	FILE *pfile;
    	PERSON *data = NULL;
    	int DatensatzNr = 1;
    
    	if((pfile = fopen(d_name, "rb")) == NULL)
    	{
    		fprintf(stderr, "Konnte %s nicht oeffnen\n", d_name);
    		exit(0);
    	}
    
    	while(fread(&data, sizeof(PERSON), 1, pfile) == 1)
    	{
    		if(first == NULL)
    		{
    			if(first = (PERSON *) malloc(sizeof(PERSON)))
    				fprintf(stderr, "Kein Speicherplatz vorhanden"
    								"fuer das Element first\n");
    
    			first->next = NULL;
    		}
    
    		else
    		{
    			data = first;
    			while(data->next != NULL)
    				data = data->next;
    			if(first = (PERSON *) malloc(sizeof(PERSON)))
    				fprintf(stderr, "Kein Speicherplatz vorhanden"
    								"fuer das Element first\n");
    
    			data = data->next;
    			data->next = NULL;
    		}
    		DatensatzNr++;
    	}
    	ausgabe();
    	fclose(pfile);
    }
    

    Ich bin am verzweifeln, ich weiß nicht wo der Fehler ist. Ich hoffe, einer von euch kann mir helfen!

    Nach dem Einlesen bekomme ich in allen Variablen

    =====================================

    zurück.

    Ciao.



  • if(first = (PERSON *) malloc(sizeof(PERSON)))
             fprintf(stderr, "Kein Speicherplatz vorhanden"
                             "fuer das Element first\n");
    

    sollte wahrscheinlich heissen

    if(first = (PERSON *) malloc(sizeof(PERSON))== 0 )
             fprintf(stderr, "Kein Speicherplatz vorhanden"
                             "fuer das Element first\n");
    

    obwohl ich persönlich diese konstrukte ( a = b == 0 ) nicht leiden kann da ich sie als schlecht lesbar halte.
    K.



  • @CaptainMeso
    Willst du den Zeiger auf das nächste Element wirklich mit den Daten speichern??


Anmelden zum Antworten