Datei fscanf ??



  • Guten Tqag, ich habe ein Problem.

    Ich muss fürs Studium eine Aufgabe lösen in der ein struct in eine Datei abgespeichert wird (soweit kein Problem) und auch wieder eingelesen werden kann.
    Hierbei wird ein Name eingelesen, aber dann werden die falschen Werte für die Zahlen übernommen.

    Das steht global:

    struct 
    {
        char vorname [21];
    	char nachname[26];
    	float gehalt [12];
    	float jahresgehalt;
    }mitarbeiter[20];
    
    int i,j,bed;
    

    So wird die Datei gespeichert:

    void speichern()
    {
          FILE *datei;     
                 datei = fopen ( "gehaltsdaten.txt" , "w");
                 if (datei == 0 ) 
                 {
                       printf ("\nDie Datei konnte nicht erstellt werden!\n"); 
                 }
                 else 
                 {
                       printf ("Die Datei wurde erstellt.\n");
    
                       for (i=0;i<=19;i=i+1)
                       {
                           fprintf (datei, "%s ",mitarbeiter[i].vorname);
                           fprintf (datei, "%s ",mitarbeiter[i].nachname);
                           for (j=0;j<=11;j=j+1)
                           fprintf (datei, "%10.2f ",mitarbeiter[i].gehalt[j]);
                           fprintf (datei, "%.2f ",mitarbeiter[i].jahresgehalt);
                       }
    
                       fclose (datei);     
                 } 
    
    }
    

    und so soll die Datei wieder eingelesen werden.

    void einlesen()
    {
    
      FILE *datei; 
    
                 datei = fopen ( "gehaltsdaten.txt" , "r");
                 if (datei == 0 ) 
                 {
                       /*  Es ist ein Fehler aufgetreten!  */
                       printf ("\nDie Datei konnte nicht erstellt werden!\n"); 
                 }
                 else 
                 {                  
                       printf ("Die Datei wird eingelesen.\n");
    
                      for (i=0;i<=19;i=i+1)
                       {
                       fscanf (datei,"%s %s",&mitarbeiter[i].vorname,&mitarbeiter[i].nachname);
                       for (j=0;j<=11;j=j+1)
                           fscanf (datei, "%f",&mitarbeiter[i].gehalt[j]);
                           fscanf (datei, "%f",&mitarbeiter[i].jahresgehalt);
                       }
    
                 } 
                 for (i=0;i<=19;i=i+1)
                       {
                       printf ("%s \n%s",&mitarbeiter[i].vorname,&mitarbeiter[i].nachname);
    
                       for (j=0;j<=11;j=j+1)
                           printf ("%f",&mitarbeiter[i].gehalt[j]);
                           printf ("%f",&mitarbeiter[i].jahresgehalt);printf("\n\n\n");
                       }
    
    }
    

    Ich hoffe mir kann jmd. helfen. Saß schon einige Stunden dran. Nun weiß ich nicht mehr weiter.

    Schnmal DANKE im vorraus.



  • Ich denke, es liegt daran, dass du beim Speichern nach jedem Gehalt ein Leerzeichen hast, das beim Lesen aber nicht berücksichtigst.

    Füge im Formatstring von fscanf noch ein Leerzeichen vor "%f" ein, dann werden führende Leerzeichen übersprungen:

    fscanf (datei, " %f",&mitarbeiter[i].gehalt[j]);
    fscanf (datei, " %f",&mitarbeiter[i].jahresgehalt);
    


  • Erstmal danke U-Boot für dein Hilfe.

    Aber es geht leider nicht. Ich hab es nochmal probiert (auf die Idee bin ich auch gekommen) aber es geht nicht. Es tritt der gleiche Fehler auf.



  • *Kopf auf den Tisch hau*
    Mann bin ich doch blind...

    printf ("%f",&mitarbeiter[i].gehalt[j]);
    printf ("%f",&mitarbeiter[i].jahresgehalt);printf("\n\n\n");
    

    Jetzt fällts mir auf, nachdem ichs ausprobiert hab:
    du versuchst, die Adresse als Float auszugeben, was ja nicht so funktionieren kann.

    Also daraus

    printf ("%f",mitarbeiter[i].gehalt[j]);
    printf ("%f",mitarbeiter[i].jahresgehalt);printf("\n\n\n");
    

    machen, dann klappts auch mit der Ausgabe.

    Durch debuggen bin ich drauf gekommen, in der Variablenüberwachung waren alle Werte richtig, also musste es an der Ausgabe liegen.

    U-Boot



  • OMG

    Ja Dankeschön, das war die Lösung.

    man beachte:

    for (i=0;i<=19;i=i+1)
                       {
                       printf ("%s \n%s",&mitarbeiter[i].vorname,&mitarbeiter[i].nachname);
    
                       for (j=0;j<=11;j=j+1)
                           printf ("%f",&mitarbeiter[i].gehalt[j]);
                           printf ("%f",&mitarbeiter[i].jahresgehalt);printf("\n\n\n");
                       }
    

    4 & zu entfernen.

    Das kommt von Copy&Paste. Aber irgendwas muss ich ja falsch machen, sonst wäre ich jetzt reicher als Bill Gates 🙂



  • ich hab ein weiteres Problem.
    er gibt die Namen als Nullen aus. Also wenn ich die Datei vorher gespeichert habe und dann einlese.

    das wäre ansich nciht schlimm, aber ich möchte mit

    /*Freien Platz suchen*/     
         j=1;
         for (i=0;j!=0;i=i+1)
         {
             j=strcmp (mitarbeiter[i].nachname,"");
         }i=i-1;
    
         printf("%d\n",i);
    

    den ersten freien speicherplatz finden. ich denke es liegt an dem Vergleich vllt. aber ich habe nirgends gefunden wie ich überprüfen kann ob ein string leer ist.

    EDIT: Der Fehler tritt nur auf, wenn ich die Datei eingelesen habe.



  • x@ero schrieb:

    ich hab ein weiteres Problem.
    er gibt die Namen als Nullen aus. Also wenn ich die Datei vorher gespeichert habe und dann einlese.

    Wie?? Bei mir werden die Namen immer normal ausgegeben. Kannst du das evtl. mal genauer erklären?

    x@ero schrieb:

    das wäre ansich nciht schlimm, aber ich möchte mit

    /*Freien Platz suchen*/     
         j=1;
         for (i=0;j!=0;i=i+1)
         {
             j=strcmp (mitarbeiter[i].nachname,"");
         }i=i-1;
         
         printf("%d\n",i);
    

    den ersten freien speicherplatz finden. ich denke es liegt an dem Vergleich vllt. aber ich habe nirgends gefunden wie ich überprüfen kann ob ein string leer ist.

    Wenn ein char[] leer ist, hat üblicherweise die erste Stelle das Zeichen '\0' (und eigentlich auch alle weiteren Stellen)



  • Eine der ältesten Regeln aus so ziemlich allen C-Schwarten: "fscanf() nicht
    verwenden, hat Risikien". Zeile einlesen, CR und LF weghauen und dann auswerten.

    Zum Strukturen Lesen und schreiben read() und write() verwenden (resp. fwrite() oder
    fread()).



  • ich hab mal den codeauszug zusammengestellt:

    #include <stdio.h>
    #include <string.h>
    
    void einlesen();
    void speichern();
    
    struct 
    {
        char vorname [21];
    	char nachname[26];
    	float gehalt [12];
    	float jahresgehalt;
    }mitarbeiter[20];
    int i,j,bed;
    
    main ()
    {
        speichern();
        einlesen();
    system ("Pause");
    }
    
    void speichern()
    {
         int a;
         printf ("Moechten Sie speichern?\n");
         printf ("Ja=1\nNein=0\n");
         scanf ("%d",&bed);
         if (bed==1)
         {
    
          FILE *datei; 
    
                 datei = fopen ( "gehaltsdaten.txt" , "w");
                 if (datei == 0 ) 
                 {
                       /*  Es ist ein Fehler aufgetreten!  */
                       printf ("\nDie Datei konnte nicht erstellt werden!\n"); 
                 }
                 else 
                 {
                       /*  Datei konnte geöffnet werden  */
    
                       for (i=0;i<=19;i=i+1)
                       {
                           fprintf (datei, "%s ",mitarbeiter[i].vorname);
                           fprintf (datei, "%s ",mitarbeiter[i].nachname);
                           for (j=0;j<=11;j=j+1)
                           fprintf (datei, "%10.2f ",mitarbeiter[i].gehalt[j]);
                           fprintf (datei, "%.2f ",mitarbeiter[i].jahresgehalt);
                       }
    
                       fclose (datei);  
                       printf ("Die Datei wurde gespeichert.\n");   
                 } 
          }
    
    }
    
    void einlesen()
    {
    
      FILE *datei; 
    
                 datei = fopen ( "gehaltsdaten.txt" , "r");
                 if (datei == 0 ) 
                 {
                       /*  Es ist ein Fehler aufgetreten!  */
                       printf ("\nDie Datei konnte nicht erstellt werden!\n"); 
                 }
                 else 
                 {  
                      for (i=0;i<=19;i=i+1)
                       {
                       fscanf (datei,"%s %s",&mitarbeiter[i].vorname,&mitarbeiter[i].nachname);
                       for (j=0;j<=11;j=j+1)
                           fscanf (datei, " %f",&mitarbeiter[i].gehalt[j]);
                           fscanf (datei, " %f",&mitarbeiter[i].jahresgehalt);
                       }
    
                 } 
                 for (i=0;i<=19;i=i+1)
                       {
                       printf ("%s %s\n",mitarbeiter[i].vorname,mitarbeiter[i].nachname);
    
                       for (j=0;j<=11;j=j+1)
                           printf ("%.2f  ",mitarbeiter[i].gehalt[j]);
                       printf ("%.2f",mitarbeiter[i].jahresgehalt);printf("\n\n\n");
                       }
    
    }
    

    so und bei der Ausgabe sind jetzt nur Nullen, was für die jeweils untere Zeile gut ist. Für die oberen 0.00 0.00 sollten die Vornamen/Nachnamen stehen. Aber weil die ja nocht leer sind sollte da doch eigentlich nichts stehen oder?

    Ich mein ich muss das dann später vergleichen. Ich dachte ich mach das mit:

    j=strcmp (mitarbeiter[i].nachname,"");
    

    nun weiß ich nicht ob das richtig ist oder ich anstatt der "" etwas anderes schreiben sollte.

    j=strcmp (mitarbeiter[i].nachname,"\0");
    

    geht auch nciht.

    EDIT: ok, werde ich mir mal ne Schwarte suchen und es dann probieren...



  • x@ero schrieb:

    ich hab mal den codeauszug zusammengestellt:

    so und bei der Ausgabe sind jetzt nur Nullen, was für die jeweils untere Zeile gut ist. Für die oberen 0.00 0.00 sollten die Vornamen/Nachnamen stehen. Aber weil die ja nocht leer sind sollte da doch eigentlich nichts stehen oder?

    Hm, ich weiss grad nicht, wie deine Ausgabe aussieht, bei mir scheints alles zu gehen. Ich schau es mir nochmal an...

    x@ero schrieb:

    Ich mein ich muss das dann später vergleichen. Ich dachte ich mach das mit:

    j=strcmp (mitarbeiter[i].nachname,"");
    

    nun weiß ich nicht ob das richtig ist oder ich anstatt der "" etwas anderes schreiben sollte.

    j=strcmp (mitarbeiter[i].nachname,"\0");
    

    geht auch nciht.

    Warum nicht einfach mit

    if(mitarbeiter[i].nachname[0] == '\0')
    {
    ...
    }
    

    , müsste doch gehen?

    Edit: Gerade deinen Code kompiliert, erstmal hab ich mit meiner vorher erstellten Datei getestet, die Ausgabe war genau wie vorher.
    Dann mit deinem Programm die neuen, leeren Daten in die Datei geschrieben, danach dann ausgeben lassen: nur noch Nullen angezeigt.

    Liegt aber daran, dass

    fprintf (datei, "%s ",mitarbeiter[i].vorname);
    fprintf (datei, "%s ",mitarbeiter[i].nachname);
    

    einfach nichts in die Datei schreibt (außer dem Leerzeichen), wenn der String leer ist! Und genau deshalb werden dann auch die ersten beiden "0.00"er, die eigentlich das Gehalt sein sollten, als Vor- und Nachname in deiner Struktur gespeichert.
    Folglich steht in den Vor-/Nachnamen der leeren Datensätze dann mit "0.00\0", darauf kannst du dann überprüfen.

    U-Boot



  • 🙂 👍 👍 👍 👍

    Vielen Vielen Dank, das geht!!!

    Mir ist zwar nicht ganz klar, wieso er dann unbedingt auf 0.00 kommt, aber es geht ja wenigstens.



  • x@ero schrieb:

    Mir ist zwar nicht ganz klar, wieso er dann unbedingt auf 0.00 kommt, aber es geht ja wenigstens.

    Auf was soll er denn sonst kommen? Schau in die Datei rein, du hast dort nur "0.00 0.00 0.00" usw. drin stehen - davon werden halt dann immer 2 als Namens-Strings interpretiert.



  • jo, das stimmt wohl.


Log in to reply