Stupider Fseek-Fehler oder rekursiver Algo?



  • Hallo meine Lieben,

    ich hoffe mir kann eventuell einer weiter helfen beim Debuggen des folgenden Codes...

    Folgende Problemdarstellung:

    - Die Eingaben werden in den Arbeitsspeicher übernommen und (teilweise) auch in die Datei gespeichert "musik_db.txt",
    nur leider unregelmäßig und nicht wirklich strukturiert.

    - Zudem liest er mit bei der Auswahl "Ausgabe" nur eine einzige Zeile der Datei aus,
    aber auch nur, wenn ich das Programm neu öffne und eine Eingabe erneut eingebe.
    Nie gibt er mir (wie bei der Parallelen Speicherung in den Arbeitsspeicher) auch nur ansatzweise die 2. Zeile aus... Die erste sowieso nicht, wenn ich das Programm neu aufrufe,
    als ob er nicht lesen kann, was in der ersten Zeile steht ... 😞

    Die Datei "musik_db.txt" wird allerdings erstellt und zumindestens in der ersten Zeile werden die Werte meiner eingegebenen Variablen gespeichert.

    Hab ich einen Denkfehler bei der fseek-Angabe
    oder hab ich mir aus Versehen einen rek-Algo gebaut?

    Hmpf... Danke für die Mithilfe meines Problems jetzt schonmal.

    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <ctype.h>
    
    #define clrscr() system("cls");
    
    int result;
    char answer;
    int zaehler;
    int i=0;
    FILE *datei;
    
    struct musiktitel
    {
        char titelname[16];
        char interpret[16];
        int dauer;
    } eingabe[100];
    
    void menue();
    void titel_eingeben();
    void titel_ausgeben();
    void datei_schreiben();
    
    int main(void)
    {
    
                char answer;
                zaehler=0;
    
        do
        {
        clrscr();    
        menue();
        int result=getch();
        if (result=='1')
        {
            zaehler++;
            titel_eingeben();
        }
        else if (result=='2')
        {
            titel_ausgeben();
        }
        else
        {
            printf ("Sie haben eine falsche Zahl eingegeben!\n(Bitte korrigieren Sie ihre Eingabe!)\n\n");
        }
        printf("\n");
        printf("Sie haben %d Titel eingegeben!(Maximum sind 100)\n\n", zaehler);
        printf("Moechten sie eine neue Auswahl treffen?(J/N)\n\n");
        answer=toupper(getchar());    
        getchar();
        }
        while (answer=='J');
    
    }
    
    void menue()
    {
      printf("Musik-Datenbank\n\n"
             "Musiktitel eingeben     1\n"
             "Musiktitel ausgeben     2\n\n"
             "Bitte waehlen Sie\n\n");
    }
    
    void titel_eingeben(struct musiktitel *tab)
    {
        clrscr();
        printf("Sie haben sich fuer 'Titel eingeben' entschieden!\n\n");
        do
        {
        fflush(stdin);   
        printf("Geben sie jetzt zuerst den Titel an!(Maximal 15 Zeichen)\n\n");
            gets(eingabe[i].titelname);
                clrscr();
                printf("Titelname:%15s\n\n", eingabe[i].titelname);
                printf("Jetzt bitte den Interpreten!(Maximal 15 Zeichen)\n\n");
                gets(eingabe[i].interpret);
                    clrscr();
                    printf("Titelname:%15s\n",eingabe[i].titelname);
                    printf("Interpret:%15s\n\n",eingabe[i].interpret);
                    printf("Wie lange dauert der Titel?(Angaben in Sekunden)\n\n");
                    scanf("%4i",&eingabe[i].dauer);
                        clrscr();
                        printf("Ihre Angaben waren wie folgt:\n\n");
                        printf("Titelname:%15s \n",eingabe[i].titelname);
                        printf("Interpret:%15s \n",eingabe[i].interpret);
                        printf("Titellaenge:%13is\n\n",eingabe[i].dauer);
                        printf("Ist das korrekt?(J/N)\n\n");
        answer=toupper(getchar());      
        getchar();
        clrscr();
            if (answer=='J')
            {
            	datei_schreiben();
                i++;
                printf("Ihre Angaben wurden gespeichert!\n\n");
            }
        }
        while (answer=='N');
    }
    
    void titel_ausgeben(void)
    {
        int z;
        clrscr();
        	datei=fopen("musik_db.txt","rb");
            rewind(datei);
                printf("\t***********************************************\n");
                printf("\t*<               Musik-Datenbank             >*\n");
                printf("\t***********************************************\n");
                printf("\t< Titelname    <>    Interpret    <>    Dauer >\n");
                printf("\t***********************************************\n");
    
                for (z=0;z<i;z++)
                {
    
                	fread(eingabe, sizeof eingabe, 1, datei);
                    printf("\t-----------------------------------------------\n");
                    printf("\t< %-15s    %-15s    %4is >\n", eingabe[z].titelname, eingabe[z].interpret, eingabe[z].dauer);
                    printf("\t-----------------------------------------------\n");
                }
                fclose(datei);
                printf("\t***********************************************\n\n");
    
    }
    
    void datei_schreiben()
    {
    	datei=fopen("musik_db.txt","a+b");
                  fseek(datei, 0 , SEEK_END);
        	fwrite(eingabe, sizeof eingabe, 1, datei);
        	fclose(datei);
    }
    

    Ming-GW-Compiler
    Programm: Eclipse



  • am besten hilft dir beim debuggen der debugger. da siehst du doch dann was passiert.



  • Hallo sn0wi,

    ich habe mir mal deinen Code angesehen und ein wenig verbessert.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    #define clrscr() system("clear");
    
    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;
    
        while (!(answer == 'J' || answer == 'N')) {
            printf("Eingabe (J/N): ");
            scanf("%c", &answer);
            getchar();
            answer = toupper(answer);
        }
    
        if (answer == 'J') return 1;
        return 0;
    }
    
    static void
    datei_schreiben(struct musiktitel *eingabe)
    {
        FILE *datei=fopen("musik_db.txt","a+b");
        fseek(datei, 0 , SEEK_END);
        fwrite(eingabe, sizeof(struct musiktitel), 1, datei);
        fclose(datei);
    }
    
    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\n");
            printf("Bitte waehlen Sie: ");
            scanf("%d", &result);
            getchar();
            if (!(result == 1 || result == 2)) {
                printf("Sie haben eine falsche Zahl eingegeben!\n");
                printf("Bitte korrigieren Sie ihre Eingabe: ");
            } else {
                break;
            }
        }
        return result;
    }
    
    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);
        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) {
            printf("\t-----------------------------------------------\n");
            printf("\t< %-15s    %-15s    %4is >\n", eingabe.titelname, eingabe.interpret, eingabe.dauer);
            printf("\t-----------------------------------------------\n");
        }
        fclose(datei);
        printf("\t***********************************************\n\n");
    }
    
    int main(void)
    {
        int   eingabe = 0;
        int   zaehler = 0;
    
        do {
            int result;
            result = menue();
            switch (result) {
            case 1:
                zaehler++;
                titel_eingeben();
                break;
            case 2:
                titel_ausgeben();
                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;
    }
    

    Nun noch ein wenig zu deinen Fehlern:

    -- scanf liest das letzte \n nicht mit, daher verwende ich getchar() nach scanf
    -- gets solltest du nicht mehr verwenden, da es nicht sicher ist. Daher
       verwende ich fgets(). Diese Funktion liest nun aber das \n mit, daher die
       Funktion remove_nextline().
    -- eingabe_ja() verwende ich nur, weil ich es netter finde.
    -- fwrite(eingabe, sizeof eingabe, 1, datei), so wie du das verwendet hast,
       schreibt nicht nur den einen Datensatz, den du neu eingegeben hast, sondern
       alle 100, weil "sizeof eingabe" so groß war.
    -- gleicher fehler bei fread.
       ich habe das dahingehend geändert, dass du jedes mal den aktuellen 
       Datensatz in die Datei schreibst. Nun klappt auch das Auslesen.
    

    So, viel Spaß mit dem korrigierten Code.

    Gruß mcr

    PS: ich weiß, da sind noch einige Sicherheitsfragen/return codes zu beachten,
    aber darum kannst du dich ja kümmern.



  • Mist, ich habe einen kleinen Fehler in meinem Code gefunden.
    Zeile 103

    Aber das schaffst du schon selber, ihn zu beseitigen. 😉

    Gruß mcr



  • Zeile 103 😉 Fehler entdeckt, rausgefiltert. ^^

    Perfekt.

    Vielen lieben Dank.



  • -gelöscht und erledigt-


Log in to reply