anzahl der filme in datei einmal zu oft ausgelesen

xbugsx

Grünschnabel
Hallo!!

Ich habe schon ein wenig im Forum geguckt ob ich ein ähnliches Thema finde, konnte aber keines finden.
Meine C-Kenntnisse sind noch nicht sehr gut und ich probiere mich durch rumprobieren.
Das Programm soll Filme abspeichern. Bei der EIngabe soll durch die EAN-Nummer geprüft werden, ob es den Film gibt. Ist er vorhanden wird nur noch die Anzahl der Filme ausgegeben. An dieser Stelle tritt auch das Problem auf. Mir wird immer ein Film zu viel angegeben.

Hier ist mal der CODE:
Code:
#include <stdio.h>
#include <string.h>

#define DATEI "movies.txt"

struct film {
	char ean[14];
	char titel[30];
};

struct film movie;
int anzahl = 0;

void speichern() {
	FILE *fp;
	
	fp = fopen(DATEI, "a+b");
	if(fp != NULL) {
		fprintf(fp, "%s",movie.ean);
		fprintf(fp, "%s",movie.titel);
		fclose(fp);
	}
	else
		printf("Fehler beim Öffnen\n");
}

void eingabe() {
	printf("Titel: ");
	fgets(movie.titel, sizeof(movie.titel), stdin);
	speichern();
}

void menge() {
	FILE *fp;

	fp = fopen(DATEI, "r+b");
	if(fp != NULL) {
		while(!feof(fp)) {
			fscanf(fp, "%s",movie.ean);
			printf("EAN: %s\n", movie.ean);
			fscanf(fp, "%s",movie.titel);
			printf("Titel: %s\n", movie.titel);
			anzahl++;
		}
		printf("Anzahl an Filmen: %i\n", anzahl);
	}
	else
		printf("Datei konnte nicht geöffnet werden\n");
	fclose(fp);
}

void vorhanden() {
	FILE *fp;
	char ean[14], *help;
	int vorhanden = 0;
	
	printf("EAN: ");
	scanf("%s",movie.ean);
	rewind(stdin);
	
	fp = fopen(DATEI, "r+b");
	if(fp != NULL) {
		while( fscanf(fp, "%s", ean) != -1) {
			if( strcmp(ean, movie.ean) == 0) {
				printf("Film schon vorhanden\n");
				vorhanden = 1;
			}
		}
		fclose(fp);
	}
	if( vorhanden == 0) {
		help = strrchr(movie.ean, '\0');
		*help = '\n';
		eingabe();
	}
}		
	
int main (int argc, const char * argv[]) {
    
	vorhanden();
	menge();
	return 0;
}

Ich würde mich freuene, wenn mir jemand sagt woran das liegt.
 
Hi.
Code:
		while(!feof(fp)) {
			fscanf(fp, "%s",movie.ean);
			printf("EAN: %s\n", movie.ean);
			fscanf(fp, "%s",movie.titel);
			printf("Titel: %s\n", movie.titel);
			anzahl++;
		}
		printf("Anzahl an Filmen: %i\n", anzahl);
Die Schleife ist falsch. Aus mehreren Gründen:

  1. du prüfst nur auf !eof - bei einem Fehler terminiert die Schleife nicht. Prüfe immer auch auf mit ferror!
  2. Du scannst die Werte ein, prüfst aber nicht ob das Einlesen erfolgreich war. Bei der vorhanden() Funktion hast du es doch auch anders gemacht!?

C:
while(fscanf(fp, "%s %s",movie.ean, movie.titel) == 2)) { 
	printf("EAN: %s\n", movie.ean);
	printf("Titel: %s\n", movie.titel);
	anzahl++;
}
Du solltest allerdings für das Einlesen des Titels des Films lieber fgets verwenden um die Zeile komplett einzulesen. scanf liest nur wortweise ein.

Gruß
 
Vielen Dank, es klappt jetzt,aber wie gesagt gibt er mir bei einem Film mit zwei Wörtern nur eines davon aus und das anderen wird dann zur EAN-Nummer.
Dazu müsste ich dann

Code:
fgets(movie.titel, sizeof(movie.titel), 1, fp)

eingeben. Aber dann würde doch

Code:
while(fscanf(fp,"%s" "%s", movie.ean, movie.titel) == 2)

nur noch zum Überprüfen der Anzahl an gelesenen Elementen des structs da sein und das einlesen macht man dann doppelt.

Ich habe auch schon mal probiert das gesamte struct
mit fwrite komplett abzuspeichern in der speichern() Funktion.

Code:
void speichern() {
	FILE *fp;
	
	fp = fopen(DATEI, "a+b");
	if(fp != NULL) {
		fwrite(&movie, sizeof(movie), 1, fp); //<---- komplette movie in die Datei
		//fprintf(fp, "%s",movie.ean); <---- anstelle dieser 
		//fprintf(fp, "%s",movie.titel); <---- beiden Funktionen
		fclose(fp);
	}
	else
		printf("Fehler beim Öffnen\n");
}

Der Inhalt wird dann auch wie bei den anderen beiden Funktionen gespeichert, doch bei der Ausgabe der Anzahl an Filmen in der menge() Funktion wird unter Titel: der Film nicht angezeigt und wenn man das Programm startet um einen weiterern Film hinzuzufügen öffnet sich der Debugger und es wird ein Fehler bei der fscanf in der vorhanden() Funktion angezeigt. Die Dateien sehen für mich identisch aus, ich habe nur an der Art wie man es abspeichert geändert und dann kam gleich ein Fehler nachdem man die EAN beim Start eingegeben hat. Ich habe die beiden dateien noch nicht mit einem Hex-Editor geöffnet um zu sehen ob sie wirklich identisch sind oder ob da vielleicht am Ende der EAN ein anderes Zeichen angehängt wird was bei dem Auswerten, ob es den Film schon gibt, einen Fehler verursacht.
Ich würde es schöner finden eine komplette Struktur abzuspeichern und zu laden. Denn dann wüsste ich je nach Anzahl der Filme die ich in eine Struktur lade wie viele Filme es gibt.
 
Vielen Dank, es klappt jetzt,aber wie gesagt gibt er mir bei einem Film mit zwei Wörtern nur eines davon aus und das anderen wird dann zur EAN-Nummer.
Dazu müsste ich dann

Code:
fgets(movie.titel, sizeof(movie.titel), 1, fp)

eingeben.
Eigentlich erwartet die Funktion fgets nur 3 Parameter.
Aber dann würde doch

Code:
while(fscanf(fp,"%s" "%s", movie.ean, movie.titel) == 2)

nur noch zum Überprüfen der Anzahl an gelesenen Elementen des structs da sein und das einlesen macht man dann doppelt.
Die Bedingung in der Schleife müßte man dann natürlich anpassen. Z.B.
C:
while (fgets(movie.ean, sizeof(movie.ean), fp) != NULL &&
        fgets(movie.titel, sizeof(movie.titel), fp) != NULL) {
   ...
}
Ich habe auch schon mal probiert das gesamte struct
mit fwrite komplett abzuspeichern in der speichern() Funktion.

Der Inhalt wird dann auch wie bei den anderen beiden Funktionen gespeichert, doch bei der Ausgabe der Anzahl an Filmen in der menge() Funktion wird unter Titel: der Film nicht angezeigt und wenn man das Programm startet um einen weiterern Film hinzuzufügen öffnet sich der Debugger und es wird ein Fehler bei der fscanf in der vorhanden() Funktion angezeigt.
Wenn du mit fwrite die Werte geschrieben hast, solltest du auch mit fread die Werte wieder auslesen. Die Dateien dürften nämlich nicht wirklich identisch sein.

Gruß
 
Jetzte funktioniert erstmal alles, Vielen Dank nochmal für die Hilfe. Bei dem fgets habe ich mich verschrieben, hatte bei den anderen fgets, ja auch nur 3 Parameter.
 
Zurück