wuschel-core
Goto Top

fread problem mit struct und Binärdatei

Hi!!
struct Datum
{
	int tt;
	int mm;
	int jj;
};

struct Person
{
	int pnr; //nr der Person
	char name[30];
	float gehalt;
	Datum gebdat;
};struct Person pers;


void delpers();
void searchpers(int);
void getpers();
void updpers();
int main ()
{
/************Ausgabe Umlaute********/
  char ue = "ü";  
  char oe = "ö";  
  char ae = "ä";  
  CharToOem(ue,ue);
  CharToOem(oe,oe);
  CharToOem(ae,ae);
/*************************************/
  int aus,wid=1;

 do
 { 
  system("cls");  
  printf (" ------------- Bitte den Men%spunkt eingeben ! -----------------\n",ue);  
  printf ("|                                                              |\n");  
  printf ("| 1.	Eingabe einer neuen Person                             |\n");  
  printf ("| 2.	W%shlen (pnr) und Ausgeben einer Person                 |\n",ae);  
  printf ("| 3.	W%shlen (pnr) und L%sschen einer Person                  |\n",ae,oe);  
  printf ("| 4.	W%shlen (pnr) und Update einer Person                   |\n",ae);  
  printf ("| 5.	Personen sortiert nach Namen ausgeben                  |\n");  
  printf ("| 6.	Personen sortiert nach Geburtsdatum ausgeben           |\n");  
  printf ("| 7.	Personen sortiert nach Name und Geburtsdatum ausgeben  |\n");  
  printf ("| 8.	Reorganisation                                         |\n");  
  printf ("|                                                              |\n");  
  printf (" --------------------------------------------------------------\n\n",ue);  
  
  printf ("                    >>> "); scanf("%i",&aus);  
  system ("cls"); //Clear Screen  
    switch(aus)
    {
      case 0:
      wid==0;
      break;
      case 1:
      getpers();
      break;
      case 2:
      printf ("Gib Nummer der Person ein die du ausgeben willst : - ");  
      scanf ("%i",&pnr);  
   **   searchpers();  **
      break;
      case 3:
      printf ("Gib Nummer der Person ein die du l%sschen willst : - ",oe);  
      scanf ("%i",&pers.pnr);  
      delpers();
      break;
      case 4:
      printf ("Gib Nummer der Person ein die du updaten willst : - ",oe);  
      scanf ("%i",&pers.pnr);  
      updpers();
      break;
      case 5:
      break;
      case 6:
      break;
      case 7:
      break;
      case 8:
      break;
      default:
      printf ("                         // Falsche Eingabe //\n\n");  
      break;
    }
 }while(wid==1);
 system("PAUSE");  
 return 0;
}




// Aufruf der Fuktion ....... Suchen einer Person, die in die Binärdatei gespeichert wurde

void getpers()
{
  fp= fopen ("pers.txt","a+b");  
  printf ("-- Bitte Daten der Person Eingeben --\n\n");  
  printf ("1. Nr = "); scanf ("%i",&pers.pnr);  
  printf ("2. Name = "); scanf ("%s",&pers.name);  
  printf ("1. Gehalt = "); scanf ("%f",&pers.gehalt);  
  printf ("1. tt.mm.jj = "); scanf ("%i.%i.%i",&pers.gebdat.tt,&pers.gebdat.mm,&pers.gebdat.jj);  
     
  fwrite (&pers,sizeof(pers),1,fp);  //Hier wird in die Binärdateigeschrieben also die geraden eingegebene Werte.
  fclose (fp);     
}

**void searchpers(int pnr)
{
fp= fopen ("pers.bin", "r+b");             //Die Datei Binär öffnen  
fseek(fp, 0L, SEEK_SET);             //Datei pointer zeigt danach auf den Anfang

 if(fp==NULL)
 printf ("\nDatei wurde nicht gefunden!\n\n");  
 
    do
    {
    fread (&pers, sizeof(pers),1,fp);               //////////////////////////////////// Genau hier stürzt er immer ab aber warum?
    }while(pnr!=pers.pnr);         // Also er macht die Schleife so lange bis pnr (das gesuchte) gleich dem pnr im

    //gerade eingelsen struct aus der Textdatei ist

    //Wenn gefunden
    printf ("\n\n    -- Die gesuchte Person - Pnr: %s - ist: --\n\n",pers.pnr);   
    printf ("    1. Name = %s\n",pers.name);  
    printf ("    2. Gehalt = %f\n",pers.gehalt);  
    printf ("    3. tt.mm.jj = %i.%i.%i\n\n",pers.gebdat.tt,pers.gebdat.mm,pers.gebdat.jj);  
    
    
    fclose(fp); //Schließen der Datei
printf ("\n\n\n");  
system ("PAUSE");  
}**


So Der fehler ist im Code markiert. fwrite also in die Binärdatei schreiben funktioniert einwandfrei.
aber fread wieder auslesen aus der Binärdatei funktioniert rein gar nicht. Also wenn ich die Zeile
mit dem fread weglassen würde das Programm funktionieren...
Mfg

Content-ID: 115167

Url: https://administrator.de/contentid/115167

Ausgedruckt am: 25.11.2024 um 22:11 Uhr

maretz
maretz 03.05.2009 um 15:41:10 Uhr
Goto Top
ganz toll - du hast nen Programm geschrieben. Herzlichen Glückwunsch!

Ansonsten wäre eine Frage hilfreich...
H41mSh1C0R
H41mSh1C0R 03.05.2009 um 15:52:32 Uhr
Goto Top
Augen auf, dann siehste das er unten ein Kommentar im Code zu stehen hat, wo steht:

" Genau hier stürzt er immer ab aber warum?"

Auch wenn das nicht so die feine Art ist tuen sich trotzdem fragen auf@Wuschel-Core. ^^

Wie lautet die Fehlermeldung?
Schon im Einzelschrittmodus durchs Programm gegangen?
KEINE Fehlerbehandlung vorhanden!!! (feof oder ferror)

Des Weiteren:
do
{
fread (pers, sizeof(struct Person),1,fp); 
}while(pnr!=pers.pnr);

Wenn ich das richtig lese, willst du immer nur den ersten Datensatz aus fp auslesen und das solange deine Bedingung ungleich ist?
76109
76109 03.05.2009 um 16:05:43 Uhr
Goto Top
Hallo wuschel-cOre,

also, erstmal bin ich ziemlich verwirrt,

Als ich mein letzten Borland 'C' Code vor ca 15 Jahren geschrieben habe, da gab's noch gewisse Syntaxregeln. So wurden z. B. Kommentare folgender Maßen gekennzeichnet, ansonsten wurde eine Syntax-Fehler ausgegeben.

Bei einer Zeile: // Kommentar für eine Zeile
Bei Blockzeilen: /* Am Anfang des Kommentarblocks und */ am Ende des Blocks

Dann schreibst Du noch Kommentare ohne irgendwas direkt hinter die Anweisungen

Zu meiner Zeit hätte das schon eine Menge an Compiler-Fehler verursacht.

Ausserdem solltest Du vielleicht mal die Funktion der Tab-Taste nutzen, um Deinen Code etwas übersichtlicher zu gestalten(Wartungsfreundlicher).

Gruß Dieter

PS. Nutze die Formatireungshilfe für Code. 1.Zeile = <$code> und letzte Zeile = <$/code> aber ohne das Dollarzeichen.
76109
76109 03.05.2009 um 16:58:41 Uhr
Goto Top
Hallo wuschel-cOre,

großes Lob. Sieht doch gleich viel besser ausface-smile

Gruß Dieter
76109
76109 03.05.2009 um 17:42:55 Uhr
Goto Top
Hallo wuschel-cOre,

Versuch mal das:

fread (&pers, sizeof(struct Person),1,fp); 

Normaler übergibst Du ja einen Buff-Pointer, aber hier musst Du, wenn ich nicht irre die Adresse (&pers) der Struct übergeben?

Probiers aus. Ist halt schon sehr lange her.

Gruß Dieter
mrtux
mrtux 03.05.2009 um 17:52:36 Uhr
Goto Top
Hi !

Zitat von @76109:
Als ich mein letzten Borland 'C' Code vor ca 15 Jahren
geschrieben habe, da gab's noch gewisse Syntaxregeln. So wurden

Ja ja damals gab es auch noch keine automatische Code Komplettierung, wir mussten den Kopf noch selber anstrengen. face-smile

Zu meiner Zeit hätte das schon eine Menge an Compiler-Fehler
verursacht.

Die heutigen IDEs, lassen doch jeden Blödsinn durchgehen. Seit dem ganzen .net Krempel, gibt es Entwickler die zwar hervorragende Kenntnisse in C++, C# oder VB haben aber nicht mal die einfachsten Hintergrundkenntnisse über das Ziel-OS haben. Wie sonst kann ich mir solchen Schwachsinn erklären, dass es Applikationen gibt, in denen z. B, die Windows Systempfade oder die Netzwerkkonfiguration hardgecoded wurden.

Mei mei mei face-smile

mrtux
76109
76109 03.05.2009 um 18:06:32 Uhr
Goto Top
Hallo mrtux,

das sind die Zeichen der Zeit. Programmieren per Drag&Dropface-smile
Für's Denken bleibt da nicht mehr soviel viel Zeit.

Gruß Dieter
maretz
maretz 03.05.2009 um 18:14:00 Uhr
Goto Top
Moin,

ok, mein Fehler... Ich bin es halt gewohnt das jemand der eine Frage hat dieses auch den möglichen Antwortgebern so deutlich wie möglich mitteilt... Denn ich lese nicht erst den gesamten Quellcode durch BEVOR ich überhaupt weiss wo das problem liegen sollte...
H41mSh1C0R
H41mSh1C0R 03.05.2009 um 18:54:23 Uhr
Goto Top
laut C Ref. kommt da kein Adressoperator hin.
mrtux
mrtux 03.05.2009 um 19:35:40 Uhr
Goto Top
Hi !

Zitat von @76109:
Hallo mrtux,
das sind die Zeichen der Zeit. Programmieren per Drag&Dropface-smile

Dagegen habe ich eigentlich nix, wenn Man(n) oder Frau weiss, was er/sie tut. Oft liegt aber genau da das Problem und nicht an der verwendeten IDE face-smile

Für's Denken bleibt da nicht mehr soviel viel Zeit.

...und wir Admins müssen den Schrott dann immer ausbaden face-sad

mrtux
Biber
Biber 03.05.2009 um 19:58:33 Uhr
Goto Top
Zitat von @76109:
Hallo wuschel-cOre,

großes Lob. Sieht doch gleich viel besser ausface-smile

Gruß Dieter
<OT>
Moin wuschel-cOre,
moin maretz, H41mSh1COR, mrtux und didi1954,

@wuschel-cOre
Ich habe Deinen Code im -sagen wir mal großzügig- "Beitrag" in Code-Tags gesetzt.

Das war jetzt der zweite lieblos hingerotzte Beitrag innerhalb von 2 Tagen.
"Drei Mal ist Bremer Recht" heißt es bei mir zu Haus - Du solltest keine zu optimistischen Analogien für Deine Beiträge daraus ableiten.

Versprechen meinerseits:
Den nächsten Mir-doch-egal-Beitrag werde ich im Fluge löschen (ohne Umweg über Papierkorb).

Grüße
Biber
</OT>
76109
76109 03.05.2009 um 19:59:27 Uhr
Goto Top
Hallo H41mSh1C0R,

wie gesagt, es ist schon sehr lange her.

also, ich würde vorschlagen den Code mit dem Debugger zu testen. Das ist die einfachste Methode einen Fehler zu findenface-smile

Aber vermutlich muss der "pers" erst noch einen (sizeof) Heap-Speicherplatz anfordern. Oder den Pointer weglassen, dann belegt die Struct Person Speicherplatz im Datensegment und kann mit "&Person" übergeben werden. So oder so ähnlich.

Gruß Dieter

PS. Wenns hilft. Ich habe noch eine uralte CD gefunden:

 struct DREC {
           DB_     ATTR;                  
           DW_     TIME; 
           DW_     DATE; 
           DD_     SIZE;   
           DB_     NAME [13];   
           DB_     RES0 [8];
           VD_    *DPTR;    
         };

  struct DREC  *DINFO;

 if ( heapinit (DINFO, sizeof (struct DREC) * 1536, 0) )   exit (1);
oder
 struct {   DD_    SZ; 
            DB_    AR; 
            DB_    AH;
            DB_    AS; 
            DB_    AD;
            DB_    AA;
            DW_    DT;
            DW_    DM;
            DW_    DJ;
            DW_    TH;
            DW_    TM;
            DW_    TS;
         }  FINFO;

 getftime ( hdl, &FINFO.TS );
 
76109
76109 03.05.2009 um 20:24:32 Uhr
Goto Top
Zitat von @Biber:
@wuschel-cOre
Ich habe Deinen Code im -sagen wir mal großzügig "Beitrag" in Code-Tags gesetzt.

Hallo Biber,

OK, dann nehme ich mein großes Lob zurück und gebe es an Dich weiter Irgendwie hat mich das gleich daran errinnert, als DU meinen ersten Code so schön formatiert hattest. War doch verdächtig perfekt formatiert.

Zitat von @mrtux:
...und wir Admins müssen den Schrott dann immer ausbaden face-sad

Hallo mrtux,

da bin ich aber froh, dass ich kein Admin bin und das ganze etwas lockerer sehen kannface-smile

Gruß Dieter
wuschel-cOre
wuschel-cOre 03.05.2009 um 23:56:24 Uhr
Goto Top
Okay Leute danke erstmal für die Hilfen mehr oder weniger!
didi1954 du hast recht. Der & Operator muss vorhanden sein.
Wird aber vom Compiler nicht als Fehler interpretiert ??
sorry wegen den formatierungen und der schlechten Beschreibung wollte eig. darauf hinaus
was beim fread der fehler war bzw. ist.

Habe noch einmal alles überarbeitet!.
Biber
Biber 04.05.2009 um 07:30:02 Uhr
Goto Top
Zitat von @wuschel-cOre:
sorry wegen den formatierungen und der schlechten Beschreibung
wollte eig. darauf hinaus was beim fread der fehler war bzw. ist.

Habe noch einmal alles überarbeitet!.
Moin wuschel-cOre,

danke Dir für das Überarbeiten.
Ist Deine Frage damit beantwortet (gelöst) oder sind noch Fragen offen?

Grüße
Biber
76109
76109 04.05.2009 um 09:47:58 Uhr
Goto Top
Hallo wuschel-cOre,

Prima, Problem gelöstface-smile

Falls Deine Programme mit der Zeit komplexer werden, würde ich Dir dringend empfehlen, Dich mit den Debugger-Funktionen vertraut zu machen, da findest Du einen Fehler in der Regel viel schneller und man lernt einiges dazu. Ideal währe es natürlich, wenn Du Dir noch Assembler-Kenntnisse aneignen würdest, damit Du auch im Assembler-Modus debuggen kannst. Dann siehst Du auch den ganzen Ablauf und was im Hintergrund so vieles unnötige passiert. Das sind zum einen Bibliotheken-Schrott und zum anderen, die falsche Auswahl einer Funktion z.B. Printf, Prints oder Puts. Was ist der Unterschied und welcher Aufwand
wird letztendlich beim Einbinden von Bibliotheksmodulen betrieben. Das soll jetzt nur mal Aufzeigen, dass man wesentlich effektiver programmieren kann, wenn man den ganzen Ablauf nachvollziehen kann.


Gruß Dieter
lowbyte1
lowbyte1 05.05.2009 um 10:08:01 Uhr
Goto Top
Helo

Nemmt doch einfach eine referenz zur Hand, oder ein schön fettes Buch auf dem c/c++ steht. Das sind keine Probleme , sondern nur unwissenheit über die Syntax der Programmiersprache.
Nicht böse gemeint ...


lb
H41mSh1C0R
H41mSh1C0R 06.05.2009 um 11:17:34 Uhr
Goto Top
Naja genau aus dieser Referenz habe ich ja gelesen und da stehen in den Beispielen KEINE "&" Operatoren an der Stelle. Hier hatte der TE aber anscheinend Erfolg, diesen & Operator zu setzen.

*grübel*

Oder die Referenz von G.Willms hat nen Fehler. ^^
76109
76109 06.05.2009 um 12:49:51 Uhr
Goto Top
Hallo H41mSh1C0R,

ich denke nicht, dass Deine Referenz fehlerhaft ist.

Der Unterschied liegt nur in der Definition einer Structur (siehe meine Beispiele). Vergleichbar mit char str[80] und char *str.

Im 1.Fall ist die Structur nur definiert und hat noch keinen Speicherplatz. Ihr wird ein *Null-Pointer zugewiesen, für den z.B. mit Malloc erst ein Speicherplatz auf dem Heap angefordert werden muss und der *Pointer dann die Adresse auf diesen Speicherplatz enthält.

Im 2.Fall ist der Structur bereits Speicherplatz im Globalen Datensegment zugewiesen. D.h. hier muss dann die Adresse mit dem Adress-Operator (&) übergeben werden.

Die Funktion Fread erwartet als Parameter einen Pointer (void *ptr) auf die Structur.


Gruß Dieter
H41mSh1C0R
H41mSh1C0R 06.05.2009 um 13:31:22 Uhr
Goto Top
Hi Dieter,

Also angewendet auf das Problem vom TE, greift Fall 2, weil mit fseek der Dateipointer an den Anfang gestellt wurde und dann mit fread bei jedem Durchlauf beginnend vom Anfang, immer Portionsweise ein Datensatz abgeholt wird.

Der Pointer auf die Struktur ist also immer die Adresse vom Anfang einer jeden Portion?

Sehe ich das richtig?

Gruß
H41mSh1C0r
76109
76109 06.05.2009 um 16:02:27 Uhr
Goto Top
Hallo H41mSh1C0R,

also, mit den Funktionen FSEEK und FREAD hat das jetzt im Grunde nichts zu Tun.

Bei TE wird mit FREAD nacheinander immer nur ein Datensatz eingelesen und FSEEK steht automatisch auf dem nächsten Datensatz.

Es geht aber generell darum, wie ein Pointer anhand der einer Definition übergeben werden muss. Adresse (&) oder Pointer (*).

Wenn eine Funktion als Parameter einen Pointer (void *ptr) verlangt, dann muss das übergeben werden, was auf die Daten zeigt.

Im 1. Fall ist *DINFO ein Pointer. Er enthält z.B. durch Malloc initialisiert, die Adresse auf die Structur DREC. DINFO = [Zeiger auf Struct-DREC]
Im 2. Fall ist FINFO die Adresse. Hier stehen die Structur-Daten schon. FINFO = Struct-Daten und &FINFO = [Zeiger auf Struct-FINFO]

Ich weiß nicht, wie ich es besser erklären kann.

Gruß Dieter
H41mSh1C0R
H41mSh1C0R 06.05.2009 um 18:38:18 Uhr
Goto Top
Hi Dieter,

dann ist das ja so wie ich das auch meine ^^.

Das was der TE mit fread abholt, enthält ja portionsweise seine Struct-Daten und somit muss der Adressoperator rein, weil die Daten/Struct ja bereits da sind.

Also Fall 2.

Gruß
H41mSh1C0r
76109
76109 06.05.2009 um 20:14:05 Uhr
Goto Top
Hallo H41mSh1C0R,

Yep, das siehst Du richtig. Offensichtlich habe ich Deine Frage wohl vorher Missverstanden.

Hoffe, nun ist alles geklärt.

Gruß Dieter
H41mSh1C0R
H41mSh1C0R 07.05.2009 um 10:51:11 Uhr
Goto Top
Hallo Dieter,

alles geklärt und danke für deine Erklärung und Beispiele.

Ist ja nicht so das ich das jeden Tag bräuchte, aber auffrischen schadet ja nie. ^^

Gruß
H41mSh1C0r