Finde Fehler bei Einlesen von File nicht



  • Hallo,

    ich habe ein kleines Programm geschrieben, mit dem ich Vektorelemente i in einen Vektoren und in ein File schreiben kann. Das klappt auch wunderbar.

    //Standartbibliotheken
    #include <stdio.h>
    #include <stdlib.h>
    
    /* 
    Es ist ein C-Programm zu erstellen, das einen Vektor über die Tastatur einliest
    und in einem File abspeichert. Der Filename ist nach dem Start des Programmes einzugeben
    */
    
    int main()
    {
        char fname [100]; //Variable für Filename (1)
        float v[100]; //Vektor (2)
        int i, n; //Variablen für if-Anweisung (3)
    
        FILE*fp; //Variable für Filezugriff (4)
    
        printf("Bitte Filenamen eingeben: "); //Ausgabe auf dem Bildschirm (5)
        scanf("%s", &fname); //Eingabe des Filenamen (6)
    
        fp=fopen(fname, "wb"); //Öffnet Datei mit oben eingegeben Filenamen (7)
        printf("Elementanzahl:"); //Ausgabe auf den Bildschirm (8)
        scanf("%d", &n); //Eingabe der Größe des Vektors (9)
    
        for (i=0; i<n; i=i+1) //Schleife für die Eingabe von den Vektorelementen (10)
        { //Anweisungen für Schleifen werden immer in {} geschrieben - Klammer #1
        printf("Element:"); //Ausgabe auf Bildschirm (11)
        scanf("%f", &v[i]); //Eingabe des Vektorelementes (12)
        fwrite (&v[i], sizeof (int), 1, fp); //schreibt ins File - näheres siehe .pdf! (13)
        } // Klammer #2 
        fclose(fp); //Schließt File (14)
    
        system("PAUSE"); //zwingt Anzeigekonsole auf Eingabe zu warten vor dem schließen (15)
        return 0; //return-Wert (16)
        }
    

    Nun möchte ich ein weiteres Programm schreiben, mit dem ich diesen Vektor auslesen lassen.

    //Standartbibliotheken
    #include<stdio.h>
    #include <stdlib.h>
    
    /* 
    Es ist ein C-Programm zu erstellen, das einen Vektor elementeweise von einem File einliest und 
    auf dem Bildschirm ausgibt. Der Filnename ist nach dem Start des Programmes einzugeben
    */
    
    int main()
    {
        int i;
        char fname[100], v[100], weiter[20];
    
        FILE*fp;
    
        printf("Bitte zu oeffnendes File angeben: ");
        gets(fname);
        fp=fopen(fname, "rb");
        if (fp==NULL)
        {
        printf("File nicht gefunden\n");
        return 1;
        }
        while(fread(&v[i],sizeof(int),1,fp)>0);
        {
        printf("%f",v[i]);
        }
          if(feof(fp))
          {
          printf("File- ENDE\n");
          }
        else
        {
        printf("File- Fehler\n");
        }
    
        fclose(fp);
    
        system("PAUSE");
        return 0;
        }
    

    Das klappt nur beschränkt. 😞

    Ich bekomme zwar eine Ausgabe, aber die ist falsch.

    Nach ewigen Suchen komme ich nicht auf des Rätsels-Lösung.
    Wie lese ich den Vektor aus?
    Theoretisch muss ich nur so lange die Ausgabe wiederholen, bis das File leer ist. Jedoch bekomme ich immer eine Ausgabe wie 0.00000

    Der Fehler liegt sicher bei

    while(fread(&v[i],sizeof(int),1,fp)>0);
        {
        printf("%f",v[i]);
        }
    

    jedoch weiß ich mir nicht zu helfen.

    Kann mir einer helfen bei meinem kleinen Problem?



  • Vielleicht solltest du mal deine Ausgaben mit den Eingaben vergleichen, vor allem die verwendeten Datentypen:

    float v[100];
    ...
    fwrite (&v[i], sizeof (int), 1, fp);
    
    char fname[100], v[100], weiter[20];
    ...
    while(fread(&v[i],sizeof(int),1,fp)>0);
    

    Beim Schreiben hast du ein Array von float und schreibst es als int (da garantiert dir schon niemand, daß die Typen gleich groß sind), beim Lesen versuchst du dann sogar, die Daten in ein char-Array zu quetschen.
    (und in der Einlese-Schleife wird i nirgends verändert, dadurch schreibst du alle Werte an die selbe Stelle im Speicher)

    PS: Und daß sich das Lese-Programm nicht mit einem SegFault verabschiedet hat, war vermutlich ein Glückstreffer.



  • Hallo,

    danke für deine Antwort!

    Ich glaube ich weiß auf was du hinaus möchtest.

    Ich habe jetzt die Variablentypen beim sizeof beim Einlesen und Ausgeben in float geändert. Darauf möchtest du doch hinaus, dass diese Variablen vom gleichen Typ sind, oder?

    Nach dem compilieren bekam ich aber die gleiche falsche Ausgabe in der Console. 😞

    Ist noch nicht ganz das wahre, glaube ich...

    PS: Und daß sich das Lese-Programm nicht mit einem SegFault verabschiedet hat, war vermutlich ein Glückstreffer.

    Wieso? Was ist ein SegFault und wieso sollte das passieren?



  • Hast du denn auch daran gedacht, die tatsächlichen Variablentypen konsistent zu verwenden? Sprich: Das Ziel beim fread() sollte auch ein float sein und kein char-Array.

    Crew06ZW schrieb:

    Wieso? Was ist ein SegFault und wieso sollte das passieren?

    SegFault = Segmentation Fault - das passiert normalerweise, wenn du in Speicherbereiche schreibst, die das Betriebssystem nicht zum Schreiben freigegeben hat. In deinem Fall hast du i nicht initialisiert, bevor du es als Array-Index verwendet hast - da ist der Inhalt nicht definiert und fread() schreibt irgendwo in den Speicher.
    (genau genommen ist bei solchen Fehlern ein SegFault noch die einfachere Variante, schlimmer wird es, wenn du in Bereiche schreibst, die das Betriebssystem nicht geschützt hast - und damit einem anderen Programmteil wichtige Daten zerstörst)



  • Während das obere Beispiel (schreiben einer Datei mit n Elementen) einigermaßen funktioniert, ist das untere voller Fehler. Also das obere ist nicht von dir 😉

    Wenn du einer Datei n Elemente zufügst, dürfen später auch nur n Elemente gelesen werden. Gibt man im oberen Beispiel an das 15 Elemente zu erfassen sind, dann liest das untere trotzdem 100 ein.

    Der Lesebefehl für das Element wird ausgeführt bevor das Dateiende mit EOF abgefragt wird. Das ist denkbar schlecht, da du gar nicht weißt, wieviele Elemte zu lesen sind. Daher solche Schleifen lieber mit

    while(!feof(fp))
    {
    Dein Code
    }

    Du könntest deiner Datei schon beim Erstellen die Anzahl der Elemente eintragen, und als erstes wieder auslesen, sonst hast du keine Möglichkeit zu prüfen ob die Daten richtig geelesen wurden .

    Gruß

    PS: und deklarier keine Arrays die du nicht brauchst (weiter) und deklarier alle variablen getrennt voneinander und nicht aus Faulheit in einer Zeile. CStoll hat dich ja schon drauf hingewiesen. Sonst werden diese Fehler immer wieder passieren.



  • Oh man, wie mich der Dreck immer ankotzt! 😡

    Das sind Übungsaufgaben für Info. Ich studiere und muss da mich mit der Programmierung rumschlagen.

    Diese Übungsaufgaben haben wir im Seminar nicht geschafft, darum wollte ich diese zu Hause lösen. Beide Programme sind von mir. Das erste läuft irgendwie und bei dem zweiten finde ich den blöden Fehler nicht!

    Ich denke doch, alle Variablen ausgetauscht zu haben, so wie es beschrieben wurde.

    Hier nochmal der geänderte Code:

    #include <stdio.h>
    #include <stdlib.h>
    
    /* 
    Es ist ein C-Programm zu erstellen, das einen Vektor über die Tastatur einliest
    und in einem File abspeichert. Der Filename ist nach dem Start des Programmes einzugeben
    */
    
    int main()
    {
        char fname [100]; 
        float v[100];
        int i, n; 
    
        FILE*fp; 
    
        printf("Bitte Filenamen eingeben: ");
        scanf("%s", &fname); 
    
        fp=fopen(fname, "wb"); 
        printf("Elementanzahl:"); )
        scanf("%d", &n); 
    
        for (i=0; i<n; i=i+1) 
        { 
        printf("Element:"); 
        scanf("%f", &v[i]); 
        fwrite (&v[i], sizeof (float), 1, fp);
        }  
        fclose(fp);
    
        system("PAUSE"); 
        return 0; 
        }
    

    und Programm 2:

    #include<stdio.h>
    #include <stdlib.h>
    
    /* 
    Es ist ein C-Programm zu erstellen, das einen Vektor elementeweise von einem File einliest und 
    auf dem Bildschirm ausgibt. Der Filnename ist nach dem Start des Programmes einzugeben
    */
    
    int main()
    {
        int i;
        char fname[100], weiter[20];
        float v[100];
    
        FILE*fp;
    
        printf("Bitte zu oeffnendes File angeben: ");
        gets(fname);
        fp=fopen(fname, "rb");
        if (fp==NULL)
        {
        printf("File nicht gefunden\n");
        return 1;
        }
        while(fread(&v[i],sizeof(float),1,fp)>0); //*
        {
        printf("%f",v[i]);
        }
          if(feof(fp))
          {
          printf("File- ENDE\n");
          }
        else
        {
        printf("File- Fehler\n");
        }
    
        fclose(fp);
    
        system("PAUSE");
        return 0;
        }
    

    Das ist doch der Ansatz den CStoll sehen wollte, oder?

    Es gibt immer Sachen die man besser machen kann, mir ist jedoch wichtig, dass das Zeug seinen Zweck erfüllt und ich eine halbwegs gute Note bekomme.

    Wo muss denn nun genau diese while Schleife vom forenseeker hin? Ich nehme an, vor die Zeile, welche ich mit einem * kommentiert habe, oder?

    Danke aber für eure Hilfe!



  • Noch nicht ganz - das Problem mit dem SegFault, das ich oben zu erklären versucht habe, hast du immer noch.
    Du schreibst alle Einträge aus der Datei an die selbe Stelle im Speicher (das i-te Element des Arrays). Und da i nicht initialisiert wurde, kann diese Stelle auch noch irgendwo im Speicher liegen.



  • Oh man, wie mich der Dreck immer ankotzt! 😡

    Immer mit der Ruhe, crewman 🙂 An der Stelle waren wir alle mal 😉

    Lehn' dich zurück, entspann' dich, und versuche einfach Schritt für Schritt dein Programm abzulesen und zu fragen, was macht der rechner an dieser Stelle und warum. In der Regel macht er das was man ihm sagt, auch wenn es falsch ist 😃

    Speicherschutzverletzung, da Variablen die nur deklariert werden, jeden Wert haben können (Zustand bei Programmstart nicht definiert). Also entweder bei der Deklaration oder vor der ersten Nutzung i=0.

    Und ja, du hast die Stelle mit //* richtig markiert.

    Schreiben:

    #include <stdio.h>
    #include <stdlib.h>
    
    /*
    Es ist ein C-Programm zu erstellen, das einen Vektor über die Tastatur einliest
    und in einem File abspeichert. Der Filename ist nach dem Start des Programmes einzugeben
    */
    
    int main()
    {
        char fname [100];
        float v[100];
        int i, n;
    
        FILE*fp;
    
        printf("Bitte Filenamen eingeben: ");
        scanf("%s", &fname);
    
        if (fp=fopen(fname, "wb"))
        {
            printf("Elementanzahl:");
            scanf("%d", &n);
    		// evtl fwrite() umm Elementezahl zu sichern
            for (i=0; i<n; i=i+1)
            {
                printf("Element %d:",i);
                scanf("%f", &v[i]);
                fwrite (&v[i], sizeof (float), 1, fp);
            }
        printf("Fertig!\n");
        fclose(fp);
        }
        else
        {
            printf("Datei konnte nicht geöffnet werden!\n");
        }
        system("PAUSE");
        return 0;
    }
    

    Und Lesen:

    #include<stdio.h>
    #include <stdlib.h>
    
    /*
    Es ist ein C-Programm zu erstellen, das einen Vektor elementeweise von einem File einliest und
    auf dem Bildschirm ausgibt. Der Filnename ist nach dem Start des Programmes einzugeben
    */
    
    int main()
    {
        int i=0; // deklarier auch int n wenn gewünscht 
        char fname[100], weiter[20]; // was ist mit weiter[20]?
        float v[100];
    
        FILE*fp;
    
        printf("Bitte zu oeffnendes File angeben: ");
        gets(fname); // gets() ist fehleranfällig
        fp=fopen(fname, "rb");
        if (fp==NULL)
        {
            printf("File nicht gefunden\n");
            return 0; // 0, denn der Fehler wurde abgefangen, Programm endet ordnungsgemäß
        }
    
        // fread(n,sizeof(int),1,fp); // evtl. Anzahl der Elemente auslesen 
    
        while(!feof(fp))
        {
            if (fread(&v[i],sizeof(float),1,fp)) {
                printf("Element %d = %f\n",i,v[i++]); //Ausgabe und i anschliessend erhöhen
            }
        }
        // evtl n mit i abgleichen
        printf("Datei enthielt %d Elemente!\n Fertig!\n", i);       
        fclose(fp);
    
        system("PAUSE");
        return 0;
    }
    

    Das Programm ist zwar immer noch anfällig für Benutzerfehler, aber es läüft.

    Gruß



  • Nicht zu fassen - es geht tatsächlich!

    Danke dafür!

    Oh man, was für eine schwere Geburt!

    Vielen Dank dafür!


Anmelden zum Antworten