struct-anzahl mit fread/fwrite übergeben



  • Hallo zusammen. ich muss für praktische informatik eine musikdatenbank in c programmieren, die daten einliest, in ne dat speichert und das ganze wieder ausgiebt. zusätzlich muss da ganze ding noch eine suchfunktion beinhalten.
    mein hauptproblem ist, dass ich ziemlich wenig ahnung von c hab, aber auch keine zeit, um mich da wirklich reinzuknieen. also bitte helft mir!!
    jetzt zu meinem eigentlichen problem:
    ich kann die daten wunderbar einlesen und in die datei speichern. wenn ich das programm allerdings schließe und wieder neu starte und direkt als erste operation die daten ausgeben lassen will, passiert nichts. wenn ich allerdings erst einen neuen eintrag erstelle und anschließend die daten ausgebe, werden alle daten ausm file ausgegeben. so wies eben sein sollte. wo liegt der fehler???

    viel text i know, aber konnt mich nicht kürzer fassen^^
    grüße und danke
    julian

    mein quelltext:
    [cpp]

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static int x = 0; /*globale variable;dient als zähler und id*/
    
    struct adres {
      char titelname[16];                         
      char interpret[16];
      int dauer;
    } adressen[100]; 
    
    void Speichern(void){
    	FILE*save = fopen("adressen.dat","r+b");
    	if(NULL == save){
    		save =fopen("adressen.dat","w+b");
    		if( NULL == save){
    			fprintf(stderr,"Kann \"adressen.dat\" nicht öffnen!\n");
    			//return EXIT_FAILURE;
    		}
    	}
    	fseek(save, 0, SEEK_END);
    	if(fwrite(&adressen, sizeof(adressen), 1, save) !=1){
    		fprintf(stderr, "Fehler bei fwrite...!!!\n");
    		//return EXIT_SUCCESS;
    	}
    	fclose(save);
    }
    
    void Eingabe(int nr, struct adres neu[]) {/*funktion eingabe*/
    	printf("Titelname : ");
    	fgets(neu[nr].titelname, 15, stdin);/*fgets liest den standart-stream stdin, kein overflow bei fgets*/
    	fflush(stdin);
    	printf("Interpret : ");
    	fgets(neu[nr].interpret, 15, stdin);
    	printf("Dauer : ");
    	fflush(stdin);
    	do{
    	scanf("%4d",&neu[nr].dauer);
    	}while(getchar()!='\n');
    
    	Speichern();
    }
    
    void Ausgabe(struct adres all[],int nr){/*funktion ausgabe*/
    	int i;
    	FILE*output =fopen("adressen.dat","r+b");
    	if( NULL == output){
    		fprintf(stderr,"Kann \"adressen.dat\" nicht öffnen!\n");
    		/*return EXIT_FAILURE;*/
    	}
    	while(fread(&adressen, sizeof(adressen), 1, output) == 1){
    		for(i = 0; i < nr; i++){
    			printf("Titelname.......:%s\n",all[i].titelname);
    			printf("Interpret......:%s\n",all[i].interpret);
    			printf("Dauer...:%d\n\n",all[i].dauer);
    				if((!(i%2))&& i!=0){
    					printf("\n\tweiter mit <Enter>\n\n");
    					getchar();
    				}
    			}
    	}
    	fclose(output);
    }
    
    int menue(void){
    	int auswahl; /*lokale variable*/
    	char c;
    
    	do{
    		printf("-1- Neue Daten eingeben\n");
    		printf("-2- Alle Daten ausgeben\n");
    		printf("-3- Programm beenden\n");
    		printf("\nIhre Auswahl :");
    		scanf("%d",&auswahl);
    
    		getchar();
    
    		switch(auswahl){ /**/
    		case 1: Eingabe(x++,adressen); break;/*Argument globale Variable x; structur adressen typ struct adres*/
    		case 2: Ausgabe(adressen,x);break;
    		case 3: printf("Ende...\n");break;
    		default: printf("Falsche Eingabe\n");break;
    		}
    	}while(auswahl !=3);/*solange klammer erfüllt wird, wird do ausgeführt*/
    
    }
    
    int main(void){
    	menue(); /*menue aufrufen */
    	return EXIT_SUCCESS;
    }
    

    [cpp]



  • Nulltens: C findest du eine Etage höher (das erledige ich, wenn ich mit der Antwort fertig bin)

    Erstens: Wieso schreibst/liest du eigentlich jedes Mal das komplette Array, auch wenn nur Teile davon gefüllt sind? Versuch's mal mit 'fread(adressen,sizeof(struct adres),100,output);'.

    Zweitens: globale Variablen sind übel - und das witzige ist, daß deine Funktionen die nötigen Wert als Parameter übernehmen und auf die globalen Werte gar nicht angewiesen sind.

    PS: und fflush(stdin) ist auch extrem fragwürdig.



  • Dieser Thread wurde von Moderator/in CStoll aus dem Forum C++ in das Forum ANSI C verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Hallo Julian,

    dein Code kommt mir sehr bekannt vor.
    Ich habe einen ziemlich identischen schon in einem anderen Thread korrigiert.
    Eine funktionierende Version findest du hier:
    "Stupider Fseek-Fehler oder rekursiver Algo?"

    Eigentlich solltet ihr solche Probleme selber lösen.

    Gruß mcr

    PS: Hm, vielleicht sollte ich mir mal angewöhnen, nicht jeden Code
    komplett zu berichtigen. *grübel*



  • wie witzig. bin wohl nicht der einzige, der das schreiben muss und auf die idee gekommen ist, im besten c-forum nachzufragen.^^
    grüße julian



  • hallo liebes forum,
    ich hänge grad schon wieder fest. diesmal an einem suchalgorithmus, mit dem man die gespeicherte datei nach einem gewissen titel durchsucht. hae das ganze mit strcmp versucht, funktioniert aber leider nicht so, wie ich das gerne hätte.
    wär echt super lieb, wenn kurz jemand drüberkucken könnte und mir meinen fehler erklären könnte...

    hier die funktion:

    [cpp]
    int titel_suchen() {
    
    	char suchen[16]; // Deklaration Typ String max 15 Zeichen
    	int f, b; // Deklaration
    	int a=0; //Initialisierung LOKALER Variablen
    	clrscr();
    	printf("Sie haben sich fuer 'Titel suchen' entschieden!\n\n");
    
    	printf("Bitte geben Sie den Titelnamen des gesuchten Stuecks ein:\n\t\t");
    			scanf("%15[a-z,A-Z]",&suchen); //formatiertes Einlesen mit
    			//Angabe: max Zeichen,
    			//zugelassene Zeichen und
    			//Adresse der Zeichenkette.
    			fflush(stdin); //Inputbuffer löschen
    
    			printf("/nsie gaben ein:%s/n",suchen);
    
    			for (a=0; ((a<100)&& (b!=1)); a++) {
    				f = strcmp(suchen, eingabe[a].titelname);
    
    				if (f == 0) {
    					printf("\n\t\tTitel gefunden\n\n\n");
    					printf("Titelname\t\tInterpret\t\tDauer\n\n");
    					printf("%-15s\t%-15s\t%i\n", eingabe[a].titelname, eingabe[a].interpret, eingabe[a].dauer);
    					b=1;
    				} else
    					b=2;
    			}
    			if (b == 2){
    			printf("\n\nDer gesuchte Teilnehmer konnte nicht gefunden werden.\n\n");
    			printf("a:%i,  b:%i",a,b);}
    					else
    					b=0;
    				}[/cpp]
    

    und hier der gesamte code:

    [cpp]
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    #define clrscr() system("cls");
    
    struct musiktitel{
        char titelname[16];
        char interpret[16];
        int  dauer;
    }eingabe[100];
    
    static void remove_nextline(char *s) {
        unsigned int i;
        for (i=0; i<strlen(s); ++i) {
            if (s[i] == '\n') s[i] = 0;
        }
    }
    
    static int eingabe_ja(void) {
        char answer = 0;/*vor der schleife answer=0*/
    
        while (!(answer == 'J' || answer == 'N')) {
            printf("Eingabe (J/N): ");
            scanf("%c", &answer);
            getchar();
            answer = toupper(answer);/*wandelt klein in großbuchstaben um*/
        }
    
        if (answer == 'J') return 1;/*wenn answer=J, rückgabe=1*/
        return 0;/*ansonsten 0*/
    }
    
    static void datei_schreiben(struct musiktitel *eingabe)
    {
        FILE *datei=fopen("musik_db.txt","a+b");
        fseek(datei, 0 , SEEK_END);/*ende der datei*/
        fwrite(eingabe, sizeof(struct musiktitel), 1, datei);/*daten werden von der adresse eingabe in den stream datei geschrieben*/
        fclose(datei);
    }
    
    int titel_suchen() {
    
    	char suchen[16]; // Deklaration Typ String max 15 Zeichen
    	int f, b; // Deklaration
    	int a=0; //Initialisierung LOKALER Variablen
    	clrscr();
    	printf("Sie haben sich fuer 'Titel suchen' entschieden!\n\n");
    
    	printf("Bitte geben Sie den Titelnamen des gesuchten Stuecks ein:\n\t\t");
    			scanf("%15[a-z,A-Z]",&suchen); //formatiertes Einlesen mit
    			//Angabe: max Zeichen,
    			//zugelassene Zeichen und
    			//Adresse der Zeichenkette.
    			fflush(stdin); //Inputbuffer löschen
    
    			printf("/nsie gaben ein:%s/n",suchen);
    
    			for (a=0; ((a<100)&& (b!=1)); a++) {
    				f = strcmp(suchen, eingabe[a].titelname);
    
    				if (f == 0) {
    					printf("\n\t\tTitel gefunden\n\n\n");
    					printf("Titelname\t\tInterpret\t\tDauer\n\n");
    					printf("%-15s\t%-15s\t%i\n", eingabe[a].titelname, eingabe[a].interpret, eingabe[a].dauer);
    					b=1;
    				} else
    					b=2;
    			}
    			if (b == 2){
    			printf("\n\nDer gesuchte Teilnehmer konnte nicht gefunden werden.\n\n");
    			printf("a:%i,  b:%i",a,b);}
    					else
    					b=0;
    				}
    
    static void titel_eingeben(void)
    {
        struct musiktitel eingabe;
        char              answer;
    
        clrscr();
        printf("Sie haben sich fuer 'Titel eingeben' entschieden!\n\n");
        do {
            printf("Geben sie jetzt zuerst den Titel an!(Maximal 15 Zeichen)\n\n");
            fgets(eingabe.titelname, 15, stdin);
            remove_nextline(eingabe.titelname);
            clrscr();
            printf("Titelname:%15s\n\n", eingabe.titelname);
            printf("Jetzt bitte den Interpreten!(Maximal 15 Zeichen)\n\n");
            fgets(eingabe.interpret, 15, stdin);
            remove_nextline(eingabe.interpret);
            clrscr();
            printf("Titelname:%15s\n",eingabe.titelname);
            printf("Interpret:%15s\n\n",eingabe.interpret);
            printf("Wie lange dauert der Titel? (Angaben in Sekunden)\n\n");
            scanf("%4i",&eingabe.dauer);
            getchar();
            clrscr();
            printf("Ihre Angaben waren wie folgt:\n\n");
            printf("Titelname:%15s \n",eingabe.titelname);
            printf("Interpret:%15s \n",eingabe.interpret);
            printf("Titellaenge:%13is\n\n",eingabe.dauer);
            printf("Ist das korrekt?\n");
            if (eingabe_ja()) {
                datei_schreiben(&eingabe);
                printf("Ihre Angaben wurden gespeichert!\n\n");
            }
        } while (answer == 'N');
    }
    
    static void titel_ausgeben(void)
    {
        struct musiktitel eingabe;
        FILE *datei=fopen("musik_db.txt","rb");
        clrscr();
        rewind(datei);/*stream-zeiger an anfang*/
        printf("\t***********************************************\n");
        printf("\t*<               Musik-Datenbank             >*\n");
        printf("\t***********************************************\n");
        printf("\t< Titelname    <>    Interpret    <>    Dauer >\n");
        printf("\t***********************************************\n");
    
        while (fread(&eingabe, sizeof(struct musiktitel), 1, datei) > 0) {/*liest aus dem stram datei in eingabe,größe musiktitel*/
            printf("\t-----------------------------------------------\n");
            printf("\t< %-15s    %-15s    %4is >\n", eingabe.titelname, eingabe.interpret, eingabe.dauer);
            printf("\t-----------------------------------------------\n");
        }
        fclose(datei);
        printf("\t***********************************************\n\n");
    }
    
    static int menue(void) {
        int result = -1;
        clrscr();
        while (1) {
            printf("Musik-Datenbank\n\n");
            printf("Musiktitel eingeben     1\n");
            printf("Musiktitel ausgeben     2\n");
            printf("Musiktitel ausgeben     3\n\n");
            printf("Bitte waehlen Sie: ");
            scanf("%d", &result);
            getchar();
            if (!(result == 1 || result == 2 || result == 3)) {
                printf("Sie haben eine falsche Zahl eingegeben!\n");
                printf("Bitte korrigieren Sie ihre Eingabe: ");
            } else {
                break;
            }
        }
        return result;
    }
    
    int main(void)
    {
        int   eingabe = 0;
        int   zaehler = 0;/*zähler startet bei 0*/
    
        do {
            int result;
            result = menue();
            switch (result) {
            case 1: zaehler++;/*zähler+1*/
                    titel_eingeben();
                    break;
    
            case 2: titel_ausgeben();
            		break;
    
            case 3: titel_suchen();
                    break;		
    
            default:break;
            }
            printf("\n");
            printf("Sie haben %d Titel eingegeben!\n\n", zaehler);
            printf("Moechten sie eine neue Auswahl treffen?\n");
            eingabe = eingabe_ja();
        } while (eingabe);
    
        return 0;
    }
    [/cpp]
    

    vielen dank und gruß
    julian



  • Auf Anhieb sehe ich das (undefinierte) "fflush(stdin);" und falsch angegebene Escape-Sequenzen /n. Und du hast zwar das Array 'struct musiktitel{...}eingabe[100];' definiert, aber titel_suchen() ist die einzige Funktion, die es verwendet (alle anderen Funktionen schreiben/lesen direkt von Festplatte).



  • Neben den Fehlern, die CStoll gefunden hat, noch folgendes:

    Da du ja im wesentlichen meine Verbesserungen verwendet hast,
    konnte ich schnell herausfinden, was bei dir schief läuft.
    Ich habe die Datensätze, die mittels titel_eingeben hinzugefügt
    werden, immer direkt in die Datei geschrieben, so dass dein
    Array eingabe[100] nie gefüllt war.

    Wenn du nun nach einem Titel suchen möchtest, mußt du vorher
    die Daten aus der Datei einlesen, oder direkt in der Datei
    suchen, was natürlich länger dauert, wenn du öfters suchst.

    In Zeile 11:

    scanf("%15[a-z,A-Z]",&suchen);
    

    ist das &-Zeichen vor suchen verkehrt.

    Außerdem solltest du bei der titel_eingabe den gleichen
    Befehl zum Eingeben verwenden, wie nachher beim Suchen.
    Z.B. habe ich in meiner musik_db.txt (übrigens ist es keine Textdatei,
    sondern eine binäre, finde daher den Suffix .txt ungünstig) den
    Titel "Hallo 2". Diesen kann ich mit deiner Routine nicht finden!

    Hier mal der verbesserte Code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    #define clrscr() system("cls");
    
    struct musiktitel {
        char titelname[16];
        char interpret[16];
        int  dauer;
    };
    
    static void remove_nextline(char *s)
    {
        unsigned int i;
        for (i=0; i<strlen(s); ++i) {
            if (s[i] == '\n') s[i] = 0;
        }
    }
    
    static int eingabe_ja(void)
    {
        char answer = 0;/*vor der schleife answer=0*/
    
        while (!(answer == 'J' || answer == 'N')) {
            printf("Eingabe (J/N): ");
            scanf("%c", &answer);
            getchar();
            answer = toupper(answer);/*wandelt klein in großbuchstaben um*/
        }
    
        if (answer == 'J') return 1;/*wenn answer=J, rückgabe=1*/
        return 0;/*ansonsten 0*/
    }
    
    static void datei_schreiben(struct musiktitel *eingabe)
    {
        FILE *datei=fopen("musik_db.txt","a+b");
        fseek(datei, 0 , SEEK_END);/*ende der datei*/
        fwrite(eingabe, sizeof(struct musiktitel), 1, datei);/*daten werden von der adresse eingabe in den stream datei geschrieben*/
        fclose(datei);
    }
    
    static int datei_lesen(struct musiktitel *eingabe, int size)
    {
        struct musiktitel tmp;
        int i = 0;
        FILE *datei=fopen("musik_db.txt", "rb");
    
        memset(eingabe, 0x0, size*sizeof(struct musiktitel));
        while (fread(&tmp, sizeof(struct musiktitel), 1, datei) > 0 && i<size) {
            eingabe[i++] = tmp;
        }
        return i;
    }
    
    static void titel_suchen(void)
    {
        struct musiktitel eingabe[100];
        char suchen[16]; /* Deklaration Typ String max 15 Zeichen */
        int a, f, b, size; /* Deklaration */
        clrscr();
        printf("Sie haben sich fuer 'Titel suchen' entschieden!\n\n");
    
        printf("Lese Daten aus Datei...\n");
        size = datei_lesen(eingabe, 100);
        printf("%d Daten eingelesen!\n", size);
    
        printf("Bitte geben Sie den Titelnamen des gesuchten Stuecks ein:\n\t\t");
        scanf("%15[a-z,A-Z]",suchen); /* <-- hier war ein fehler */
        getchar();
    
        printf("\nsie gaben ein:%s\n",suchen);  
    
        for (a=0; ((a<size)&& (b!=1)); a++) {
            f = strcmp(suchen, eingabe[a].titelname);
    
            if (f == 0) {
                printf("\n\t\tTitel gefunden\n\n\n");
                printf("Titelname\t\tInterpret\t\tDauer\n\n");
                printf("%-15s\t%-15s\t%i\n", eingabe[a].titelname, eingabe[a].interpret, eingabe[a].dauer);
                b=1;
            } else
                b=2;
        }
        if (b == 2){
            printf("\n\nDer gesuchte Teilnehmer konnte nicht gefunden werden.\n\n");
            printf("a:%i,  b:%i",a,b);
        }
    }
    
    static void titel_eingeben(void)
    {
        struct musiktitel eingabe;
        char              answer;
    
        clrscr();
        printf("Sie haben sich fuer 'Titel eingeben' entschieden!\n\n");
        do {
            printf("Geben sie jetzt zuerst den Titel an!(Maximal 15 Zeichen)\n\n");
            fgets(eingabe.titelname, 15, stdin);
            remove_nextline(eingabe.titelname);
            clrscr();
            printf("Titelname:%15s\n\n", eingabe.titelname);
            printf("Jetzt bitte den Interpreten!(Maximal 15 Zeichen)\n\n");
            fgets(eingabe.interpret, 15, stdin);
            remove_nextline(eingabe.interpret);
            clrscr();
            printf("Titelname:%15s\n",eingabe.titelname);
            printf("Interpret:%15s\n\n",eingabe.interpret);
            printf("Wie lange dauert der Titel? (Angaben in Sekunden)\n\n");
            scanf("%4i",&eingabe.dauer);
            getchar();
            clrscr();
            printf("Ihre Angaben waren wie folgt:\n\n");
            printf("Titelname:%15s \n",eingabe.titelname);
            printf("Interpret:%15s \n",eingabe.interpret);
            printf("Titellaenge:%13is\n\n",eingabe.dauer);
            printf("Ist das korrekt?\n");
            if (eingabe_ja()) {
                datei_schreiben(&eingabe);
                printf("Ihre Angaben wurden gespeichert!\n\n");
            }
        } while (answer == 'N');
    }
    
    static void titel_ausgeben(void)
    {
        struct musiktitel eingabe;
        FILE *datei=fopen("musik_db.txt","rb");
        clrscr();
        rewind(datei);/*stream-zeiger an anfang*/
        printf("\t***********************************************\n");
        printf("\t*<               Musik-Datenbank             >*\n");
        printf("\t***********************************************\n");
        printf("\t< Titelname    <>    Interpret    <>    Dauer >\n");
        printf("\t***********************************************\n");
    
        while (fread(&eingabe, sizeof(struct musiktitel), 1, datei) > 0) {/*liest aus dem stram datei in eingabe,größe musiktitel*/
            printf("\t-----------------------------------------------\n");
            printf("\t< %-15s    %-15s    %4is >\n", eingabe.titelname, eingabe.interpret, eingabe.dauer);
            printf("\t-----------------------------------------------\n");
        }
        fclose(datei);
        printf("\t***********************************************\n\n");
    }
    
    static int menue(void)
    {
        int result = -1;
        clrscr();
        while (1) {
            printf("Musik-Datenbank\n\n");
            printf("Musiktitel eingeben     1\n");
            printf("Musiktitel ausgeben     2\n");
            printf("Musiktitel suchen       3\n\n");
            printf("Bitte waehlen Sie: ");
            scanf("%d", &result);
            getchar();
            if (!(result == 1 || result == 2 || result == 3)) {
                printf("Sie haben eine falsche Zahl eingegeben!\n");
                printf("Bitte korrigieren Sie ihre Eingabe: ");
            } else {
                break;
            }
        }
        return result;
    }
    
    int main(void)
    {
        int   eingabe = 0;
        int   zaehler = 0;/*zähler startet bei 0*/
    
        do {
            int result;
            result = menue();
            switch (result) {
            case 1: zaehler++;/*zähler+1*/
                    titel_eingeben();
                    break;
    
            case 2: titel_ausgeben();
                    break;
    
            case 3: titel_suchen();
                    break;
    
            default:break;
            }
            printf("\n");
            printf("Sie haben %d Titel eingegeben!\n\n", zaehler);
            printf("Moechten sie eine neue Auswahl treffen?\n");
            eingabe = eingabe_ja();
        } while (eingabe);
    
        return 0;
    }
    

    Hier sind noch ein paar Fehler drinnen, korrigiert die doch mal.

    Gruß mcr



  • ok jetzt funktionier alles. vielen dank euch beiden, vorallem dir mcr, ohne dich hätt ich das sicher nicht hinbekommen!!!
    tausend dank und grüße
    julian



  • zwei fragen sind jetz noch aufgetaucht.
    un zwar könntest du mir als leihen mal erklären, was genau hier passiert??

    [cpp]static void remove_nextline(char *s)
    {
        unsigned int i;
        for (i=0; i<strlen(s); ++i) {/*länge des strings*/
            if (s[i] == '\n') s[i] = 0;
        }
    }[/cpp]
    

    prinzipiell ist mir das schon klar, aber nicht im detail...

    und hiermit komm ich auch nochnicht wirklich klar:

    [cpp]static int datei_lesen(struct musiktitel *eingabe, int size)
    {
        struct musiktitel tmp;
        int i = 0;
        FILE *datei=fopen("musik_db.txt", "rb");
    
        memset(eingabe, 0x0, size*sizeof(struct musiktitel));/*schreibt eingabe in die ersten bites von struct*/
        while (fread(&tmp, sizeof(struct musiktitel), 1, datei) > 0 && i<size) {
            eingabe[i++] = tmp;
        }
        return i;
    }[/cpp]
    

    was genau macht denn jetzt memset? habe dafür keine richtige erklärung gefunden...

    grüße un danke^^
    julian



  • Hallo Julian,

    julian06 schrieb:

    zwei fragen sind jetz noch aufgetaucht.
    un zwar könntest du mir als leihen mal erklären, was genau hier passiert??

    static void remove_nextline(char *s)
    {
        unsigned int i;
        for (i=0; i<strlen(s); ++i) {/*länge des strings*/
            if (s[i] == '\n') s[i] = 0;
        }
    }
    

    prinzipiell ist mir das schon klar, aber nicht im detail...

    strlen liefert die Länge des Strings zurück, genauer gesagt die Anzahl
    der Chars bis zum nächsten '\0'. Die for-schleife ersetzt alle Vorkommen
    des Zeichens '\n' durch '\0', dem String-Ende-Zeichen.
    Das Problem besteht darin, dass fgets das '\n' mit in die Variable speichert
    und du das mit Sicherheit nicht in deinen Datensätzen haben möchtest.
    Kannst die Funktion ja mal entfernen, um zu sehen, was passiert.

    *char *fgets(char *s, int size, FILE stream);
    fgets() liest hochstens size minus ein Zeichen von stream und
    speichert sie in dem Puffer, auf den s zeigt. Das Lesen stoppt nach
    einem EOF oder Zeilenvorschub. Wenn ein Zeilenvorschub gelesen wird,
    wird er in dem Puffer gespeichert. Ein '\0' wird nach dem letzten
    Zeichen im Puffer gespeichert.

    julian06 schrieb:

    und hiermit komm ich auch nochnicht wirklich klar:

    static int datei_lesen(struct musiktitel *eingabe, int size)
    {
        struct musiktitel tmp;
        int i = 0;
        FILE *datei=fopen("musik_db.txt", "rb");
    
        memset(eingabe, 0x0, size*sizeof(struct musiktitel));
        while (fread(&tmp, sizeof(struct musiktitel), 1, datei) > 0 && i<size) {
            eingabe[i++] = tmp;
        }
        return i;
    }
    

    was genau macht denn jetzt memset? habe dafür keine richtige erklärung gefunden...

    grüße un danke^^
    julian

    memset initialisiert size*sizeof(struct musiktitel) Bytes mit 0.

    void *memset(void *s, int c, size_t n);
    Die Funktion memset() schreibt n mal die Bytekonstante c in den
    Speicherbereich, auf den s zeigt.

    Die while-schleife liest, solange Datensätze in der Datei vorhanden sind,
    diese ein und speichert sie im Array eingabe[].

    Noch Fragen?



  • Aber btw, du solltest dir mal ein gutes C-Buch kaufen und ein wenig
    darin nachlesen.

    Noch einen Tip: google mal nach "man memset", dann hättest du auch
    die Erklärung zu memset gefunden. 😉

    Ach ja, darf ich fragen, welches Betriebssystem verwendest?



  • morgen. vielen dank erstmal. ich hab mir bereits den schinken c von a bis z zugelegt, konnte aber zum thema memset nichts befriedigendes finden. ich benutze übrigens winxp.

    also wenn ich das jetzt richtig verstanden habe, wandelt die funktion remove_nextline alle /n in /0. bedeutet das dann, dass fgets quasi jedes wort einzeln speichert und nicht nen kompletten satz inklusive leerzeichen?

    und könntest du mir das hier

    [cpp]memset(eingabe, 0x0, size*sizeof(struct musiktitel));
        while (fread(&tmp, sizeof(struct musiktitel), 1, datei) > 0 && i<size) {
            eingabe[i++] = tmp;
        }[/cpp]
    

    nochmal gaaaanz langsam punkt für punkt in worten erklären, was da passiert?
    ich steig da immernochnicht durch.. was bedeutet zb 0x0?
    sry wenn ich mich da zugegebenermaßen etwas dümmlich anstelle, aber wurde vor 4 wochen das erste mal mit c konfroniert...
    danke und grüße
    julian



  • julian06 schrieb:

    also wenn ich das jetzt richtig verstanden habe, wandelt die funktion remove_nextline alle /n in /0. bedeutet das dann, dass fgets quasi jedes wort einzeln speichert und nicht nen kompletten satz inklusive leerzeichen?

    Zum Einen, ja es wandelt jedes \n in \0 um. (Das ist ein
    Back-Slash kein normaler Slash!!)
    Zum Anderen, nein, lies dir mal die Beschreibung (man-page) von fgets
    durch. Die Funktion liest solange Zeichen ein, bis es ein \n, das Ende
    EOF gefunden hat oder der Buffer (size-1) voll ist.

    julian06 schrieb:

    und könntest du mir das hier

    memset(eingabe, 0x0, size*sizeof(struct musiktitel));
        while (fread(&tmp, sizeof(struct musiktitel), 1, datei) > 0 && i<size) {
            eingabe[i++] = tmp;
        }
    

    Das sollte eigentlich in deinem Buch beschrieben sein. 0x0 bedeutet einfach
    nur 0. Ich habe es nur in hex-Schreibweise angegeben.
    Die memset-Zeile initialisiert den Speicher eingabe mit lauter Nullen.
    i++ ist das selbe wie i=i+1;
    fread() liefert die Anzahl der erfolgreich gelesenen Datensätze zurück.
    Da hier immer nur einer eingelesen wird, sollte da immer eine 1 zurück kommen,
    es sei denn, die Datei ist komplett eingelesen, dann kommt eine 0 zurück.
    i<size passt auf, dass nicht mehr Datensätze eingelesen werden, als Speicher
    zur Verfügung steht.
    Ach ja, der Datensatz wird von fread in tmp gespeichert.
    So noch Fragen?

    Vielleicht solltest du dir das Buch auch mal durchlesen. Das ist alles
    Standardcode, nichts besonderes. Und vielleicht ist ein Schinken zum
    Programmieren lernen nicht besonders empfehlenswert. Ich hätte mir ein
    Anfängerbuch gekauft: Vielleicht den Kerningham, Ritchie; "The C Programming
    Language";



  • die sache mit fgets ist mir jetzt klar. hab newline mit nem leerzeichen verwechselt...peinlich...

    aber nochmal zur zweiten funktion:
    warum schreibst du das denn in hexa? hat das vorteile oder ist das nur so aus ner laune heraus?^^
    du schreibst, dass mit hilfe von memset der speicher "eingabe" komplett mit nullen gefüllt wird. der speicher eingabe wird also sozusagen komplett entlehrt?

    fread() liefert die Anzahl der erfolgreich gelesenen Datensätze zurück.

    verstehe.

    Da hier immer nur einer eingelesen wird, sollte da immer eine 1 zurück kommen,
    es sei denn, die Datei ist komplett eingelesen, dann kommt eine 0 zurück.

    das heißt, es wird ein eintrag nach dem anderen aus datei gelesen und in temp registriert, bis size erreicht ist? wobei jedes mal wenn temp "angesprochen" wird, i um eins erhöht wird?

    die größe von size wiederum wird hierdurch definiert?

    size*sizeof(struct musiktitel)

    Das ist alles
    Standardcode, nichts besonderes.

    für dich ja. für mich nein.^^
    grüße und danke
    julian



  • Hi,

    ich habe da hex genommen, weil ich dort einfacher die Bitbelegung
    ablesen kann. Hat sonst keinen anderen Hintergrund.

    das heißt, es wird ein eintrag nach dem anderen aus datei gelesen und in
    temp registriert, bis size erreicht ist? wobei jedes mal wenn temp
    "angesprochen" wird, i um eins erhöht wird?

    Fast: es wird in tmp zwischen- und anschließend unter
    eingabe[i] dauerhaft gespeichert. Die Schleife bricht entweder ab, wenn
    es keine Datensätze mehr in der Datei zu lesen gibt, oder wenn size (=100)
    viele Datensätze gelesen wurden.

    Hier vielleicht mal der Code ohne irgendwelche Abkürzungen:

    static int datei_lesen(struct musiktitel *eingabe, int size)
    {
        struct musiktitel tmp;
        int i, gelesen;
        FILE *datei=fopen("musik_db.txt", "rb");
    
        memset(eingabe, 0x0, size*sizeof(struct musiktitel));
        i = 0;
        gelesen = fread(&tmp, sizeof(struct musiktitel), 1, datei);
        while (gelesen > 0 && i<size) {
            eingabe[i] = tmp;
            i = i+1;
            gelesen = fread(&tmp, sizeof(struct musiktitel), 1, datei);
        }
        return i;
    }
    

    Ist der nun verständlicher?

    die größe von size wiederum wird hierdurch definiert?

    Nein, size gibt an, wieviele Elemente für eingabe vorgesehen wird.
    Diese Zahl darf nicht überschritten werden und sollte die gleiche
    sein, wie in Zeile 60:

    struct musiktitel eingabe[100];  /*<-- size = 100*/
    

    wie du in zeile 68 sehen kannst:

    size = datei_lesen(eingabe, 100);
    

    size*sizeof(struct musiktitel)

    berechnet die benötigten Bytes für eingabe.

    So, nun sollten aber alle Fragen beantwortet sein, oder?



  • ja super vielen dank nochmal.
    deine mühe hat mir wirklich sehr geholfen.
    grüße julian


Anmelden zum Antworten