komplettes struct mit fprintf in Datei schreiben?



  • es wird binär geschrieben. das ist ein für menschen schwer bis nicht lesbares format.

    beim öffnen mach "wb". das "b" muss dabei sein.



  • Es wird der Inhalt von computer in das file geschrieben und zwar der Inhalt von 1 Element. Hättest du Feld von Daten müßtest du hier die Anzahl der Elemente die du schreiben möchtest eintragen.

    Solange du den Copmpiler oder das Betriebssystem nicnt wechselts wird du damit keine Probleme haben, Ansonsten machen dir die Füllbytes oder das Byte ordering Probleme.

    Beim MSVC 6.0 ist zum Beispiel das Alignment per default auf 4 gesetzt. d.h damit der Processor auf die Daten optimal zugreifen kann fangen alle Elemente der Stuktur auf einer durch 4 teilbaren Adresse an d.h Nach Name kommt ein Füllbyte, nach den anderen keines. Ist das Alignment auf 8 kommt nach name 1 Füllbyte nach raum, benutzer, login_zeit jeweils 4 Füllbytes. Wie die Füllbytes angeordnet werden entschidet leider der Compüilerhersteller. Es gibt oftmals auch eine Möglichkeit die Daten packed in der Struktur zu speichern, dann fallen die Füllbytes weg, aber die Performance leidet etwas.

    struct daten
    {
    char name[15];
    int raum;
    char benutzer[20];
    char login_zeit[20];
    } computer;



  • PAD, is das nicht schon klar?

    das problem beim schreiben ist, wenn das "b" fehlt, bestimmte zeichen (ein \r\n in ein \n) umgewandelt werden.



  • Meines wissens wirkt diese Spezialität der Microsoftwelt mit dem b nur beim fprintf/fputs statement. Das fwrite ist glaube ich nicht davon betroffen. Er dürfte bei seiner Struktur folgender "eigentümlichkeiten" sehen
    - die \0 die die Strings beenden,
    - die undefinierten Zeichen nach dem \0 bis zum Feldende,
    - die Füllbytes
    - die interne Darstellung der Integer Zahl als Int32
    - glücklicherweise hat er keine floats/double dabei

    🙂



  • Danke erstmal an Alle 🙂

    Also, da der compiler gleich ist, das betriebssystem aber wechselt, habe ich es dann doch so gemacht:

    printf("\n\nBitte geben Sie jetzt die Daten an:\n");
    printf("\nPC-Name   : ");
    gets(computer.name);
    printf("\nRaum      : ");
    gets(computer.raum);
    printf("\nBenutzer  : ");
    gets(computer.benutzer);
    printf("\nLogin-Zeit: ");
    gets(computer.login_zeit);
    FILE *pc_datenbank;
    pc_datenbank = fopen("archiv.txt","a");
    fprintf(pc_datenbank, "\n__________________________________\n\n");
    fprintf(pc_datenbank, "PC-Name:    %s\n", computer.name);
    fprintf(pc_datenbank, "Raum:       %s\n", computer.raum);
    fprintf(pc_datenbank, "Benutzer:   %s\n", computer.benutzer);
    fprintf(pc_datenbank, "Login-Zeit: %s\n", computer.login_zeit);
    fclose(pc_datenbank);
    

    Die von euch genannten Methoden haben auf jeden Fall auch funktioniert, aber da es sich hierbei um eine Schularbeit, die benotet wird, handelt, will ich mal lieber auf Nummer sicher gehen 😉

    Habe noch drei andere Fragen, für die ich keinen neuen Thread eröffnen wollte und auf die ich im Forum leider keine Antwort gefunden habe:

    1. Wie kann ich eine leere Seite ausgeben? Ich möchte zum Beispiel einen Punkt aus meinem Hauptmenü wählen und das Ergebnis soll dann auf einer neuen Seite angezeigt werden, also am oberen Bildrand soll man das Hauptmenü nicht mehr sehen.
    2. Ist es möglich, dass ich eine Art Scrollmechanismus einbaue, für den Fall das meine Datei irgendwann zu lang wird und nicht alle Ergebnisse auf den Bildschirm passen?
    3. Kennt ihr vielleicht ein gutes Tutorial wo ich lesen kann, wie man einzelne Daten der Datei später wieder einlesen und bearbeiten kann?

    Hoffe mal, ihr habt eine Antwort auf meine Fragen oder lest sie wenigstens mal, ansonsten eröffne ich vielleicht doch noch einen neuen Thread 😃

    Vielen Dank an euch!
    Dank diesem Forum habe ich schon eine Menge dazu gelernt 🙂



  • sowie es ein \n für eine neue Zeile gibt, gibt es auch eine Zeichen für formfeed

    Escape Sequence Represents
    \a Bell (alert)
    \b Backspace
    \f Formfeed
    \n New line
    \r Carriage return
    \t Horizontal tab
    \v Vertical tab
    \' Single quotation mark
    \" Double quotation mark
    \\ Backslash
    \? Literal question mark
    \ooo ASCII character in octal notation
    \xhhh ASCII character in hexadecimal notation

    1. Wenn du in einem Dos-Fenster arbeitest nicht
    2. Wenn du das ganze in einer Windowsapplikation machst bieten sich Listboxen an
    3. Das sinnvolle Gegenstück zu fprintf ist fgets (oder fscanf) Jedes C-Buch bietet genügend Informationen zum lesen eines Files an. (z.B auch unter Behandlung von while Schleifen) oder schau dich hier im forum um (file lesen)



  • Wieso machst du das ganze mit fprintf,FILE,fopen ... etc.?
    Willst du es so machen oder musst du???

    Ich würde es ganz einfach mit open write read und close machen!

    Datei öffnen:

    int Datei = open ("computer_daten.dat",O_RDWR | O_CREAT | O_BINARY, 0666);
    

    in Datei schreiben,(in deinem fall dass struct pc_datenbank):

    write(Datei,&pc_datenbank,sizeof(pc_datenbank));
    

    und später wieder genau gleich aus der Datei ins struct pc_datenbank laden:

    read(Datei,&pc_datenbank,sizeof(pc_datenbank));
    

    und zum schluss:

    close(Datei);
    

    fertig!

    mfg hohesC 🙂

    [edit]io.h und fcntl.h sind zu includeieren[/edit]



  • PAD schrieb:

    sowie es ein \n für eine neue Zeile gibt, gibt es auch eine Zeichen für formfeed

    Escape Sequence Represents
    \a Bell (alert)
    \b Backspace
    \f Formfeed
    \n New line
    \r Carriage return
    \t Horizontal tab
    \v Vertical tab
    \' Single quotation mark
    \" Double quotation mark
    \\ Backslash
    \? Literal question mark
    \ooo ASCII character in octal notation
    \xhhh ASCII character in hexadecimal notation

    1. Wenn du in einem Dos-Fenster arbeitest nicht
    2. Wenn du das ganze in einer Windowsapplikation machst bieten sich Listboxen an
    3. Das sinnvolle Gegenstück zu fprintf ist fgets (oder fscanf) Jedes C-Buch bietet genügend Informationen zum lesen eines Files an. (z.B auch unter Behandlung von while Schleifen) oder schau dich hier im forum um (file lesen)

    Morgen PAD 🙂

    Ich habe die Escape-Sequenz für Formfeed schon ausprobiert, aber leider hat es nicht funktioniert. Es wird doch genauso mit printf() ausgegeben, wie z.B. \n, oder?

    Werde mich mal zu fgets informieren. Wenn es klappt, dann poste ich es hier.

    Ist es eigentlich sinnvoller die Daten binär oder im Textmodus in die Datei zu schreiben?

    Vielen Dank für deine Hilfe 🙂



  • hohesC schrieb:

    Wieso machst du das ganze mit fprintf,FILE,fopen ... etc.?
    Willst du es so machen oder musst du???

    Ich würde es ganz einfach mit open write read und close machen!

    Datei öffnen:

    int Datei = open ("computer_daten.dat",O_RDWR | O_CREAT | O_BINARY, 0666);
    

    in Datei schreiben,(in deinem fall dass struct pc_datenbank):

    write(Datei,&pc_datenbank,sizeof(pc_datenbank));
    

    und später wieder genau gleich aus der Datei ins struct pc_datenbank laden:

    read(Datei,&pc_datenbank,sizeof(pc_datenbank));
    

    und zum schluss:

    close(Datei);
    

    fertig!

    mfg hohesC 🙂

    [edit]io.h und fcntl.h sind zu includeieren[/edit]

    Hallo hohesC 🙂

    Was ist denn der Vorteil deiner Variante gegenüber meiner (abgesehen von weniger Code)?
    Also es ist nicht festgeschrieben wie ich es mache, es war halt die Variante die ich bereits kannte.
    Auf jeden Fall habe ich deine Methode mal ausprobiert, aber mein Compiler meldet mir "undefined identifier 'O_RDWR', 'write' und 'close'.
    was für eine header-Datei muss ich hierfür includen? Könnte aber auch an meinem Compiler liegen. Zu Hause benutze ich Borland, aber zur Zeit bin ich auf Arbeit und hier benutze ich so einen spartanischen MS-DOS Compiler.

    Danke 🙂



  • Aleks schrieb:

    Ich habe die Escape-Sequenz für Formfeed schon ausprobiert, aber leider hat es nicht funktioniert. Es wird doch genauso mit printf() ausgegeben, wie z.B. \n, oder?

    try this out:

    clrscr();

    vorher conio.h includieren.



  • io.h und fcntl.h sind zu includeieren



  • du schreibst mit write das gesamte struct in eine Datei
    und liest es mit read ganz einfach wieder aus und hast es wieder 100% identisch wie vorher in deinem struct, kannst es bearbeiten etc. einfacher gehts doch nicht!?

    mfg hohesC



  • Hallo ALEKS
    - Das Formfeed sollte wie \n funktionieren

    - wenn du auf einem PC in einer DOS-Box oder auf einem DOS-PC arbeitest, funktioniert das mit clrscr(), sonst nicht.

    - ich ziehe textbasierte Lösungen vor. siehe unten
    ---------------------------------------------------
    Hallo Hohes C

    Wie du weiter oben siehst, hat er eine adequate Lösung mit fwrite schon selber überlegt, ist dann aber wieder zu einer HRM (human readable material) Lösung zurückgekehrt. Aus meiner Sicht ist so eine ASCII Lösung gerade für solche Projekte deutlich übersichtlicher als eine Binäre Lösung, die dann meist auch noch CPU-abhängig (little/big endian) ist.

    Wenn man bedenkt das ganze Betriebssysteme mit solchen ASCII-Datein konfiguriert und gesteuert werden sind sie für mich sinnvoller als binär Dateien.

    Die meisten meiner Lösungen basieren ebenfalls auf ASCII-Dateien. Binäere Datein benutze ich nur dann, wenn es deutlich Performance Vorteile gibt, oder die Binäerdateien für große Files (>10MB) deutlich kleiner als ASCII-Dateien sind.

    ASCII-Datein, sind speziell bei Programmabstürzen oftmals besser zu retten als Binaerdateien.
    Während der Entwicklungsphase sind sie auch viel hilfreicher als binäre. Kommen
    Informationen hinzu kann man diese oftmals in bestehende Files "per Hand" nachrüsten. Bei Binäerdateien muß ich mir einen Konverter schreiben.

    😃



  • PAD schrieb:

    Hallo ALEKS
    - Das Formfeed sollte wie \n funktionieren

    - wenn du auf einem PC in einer DOS-Box oder auf einem DOS-PC arbeitest, funktioniert das mit clrscr(), sonst nicht.

    - ich ziehe textbasierte Lösungen vor. siehe unten
    ---------------------------------------------------
    Hallo Hohes C

    Wie du weiter oben siehst, hat er eine adequate Lösung mit fwrite schon selber überlegt, ist dann aber wieder zu einer HRM (human readable material) Lösung zurückgekehrt. Aus meiner Sicht ist so eine ASCII Lösung gerade für solche Projekte deutlich übersichtlicher als eine Binäre Lösung, die dann meist auch noch CPU-abhängig (little/big endian) ist.

    Wenn man bedenkt das ganze Betriebssysteme mit solchen ASCII-Datein konfiguriert und gesteuert werden sind sie für mich sinnvoller als binär Dateien.

    Die meisten meiner Lösungen basieren ebenfalls auf ASCII-Dateien. Binäere Datein benutze ich nur dann, wenn es deutlich Performance Vorteile gibt, oder die Binäerdateien für große Files (>10MB) deutlich kleiner als ASCII-Dateien sind.

    ASCII-Datein, sind speziell bei Programmabstürzen oftmals besser zu retten als Binaerdateien.
    Während der Entwicklungsphase sind sie auch viel hilfreicher als binäre. Kommen
    Informationen hinzu kann man diese oftmals in bestehende Files "per Hand" nachrüsten. Bei Binäerdateien muß ich mir einen Konverter schreiben.

    😃

    Hallo PAD 🙂

    das mit dem Formfeed funktioniert leider nicht. An der Stelle, wo eine neue Seite angezeigt werden sollte, wird einfach das Symbol für weiblich angezeigt 😕

    @hohesC:
    Wozu braucht man in deiner Methode eigentlich noch pc_datenbank? Als Pointer kann man es laut deiner Methode gar nicht benutzen, oder wie kann ich das verstehen?

    Danke für eure Hilfe 🙂



  • das ist der name des structs
    ich hab das struct einfach mal pc_datenbank genannt!

    struct daten 
    { 
     char name[15]; 
     int raum; 
     char benutzer[20]; 
     char login_zeit[20]; 
    } pc_datenbank;
    

    änder pc_datenbank in den namen deines structs! ich glaub computer heist dein struct!

    mfg hohesC



  • hohesC schrieb:

    das ist der name des structs
    ich hab das struct einfach mal pc_datenbank genannt!

    struct daten 
    { 
     char name[15]; 
     int raum; 
     char benutzer[20]; 
     char login_zeit[20]; 
    } pc_datenbank;
    

    änder pc_datenbank in den namen deines structs! ich glaub computer heist dein struct!

    mfg hohesC

    So, das habe ich jetzt auch getestet. Allerdings ist mir ein Problem aufgefallen. Bei jedem neuen Speichern in die Datei werden die alten Daten überschrieben.

    Gibt es da irgendeine Möglichkeit das zu verhindern?

    Danke 🙂



  • ja!
    mit

    lseek(Datei,0L,SEEK_END);
    

    springst du ans ende der datei und schreibst dort weiter!

    mfg hohesC



  • nimm für dein programm lieber ein struct array!

    struct daten 
    { 
     char name[15]; 
     int raum; 
     char benutzer[20]; 
     char login_zeit[20]; 
    } computer[100];
    

    dann musst du mit

    lseek(Datei,0L,SEEK_SET);
    

    immer auf den anfang springen um zu speichern.
    hast es dann aber alles identisch wieder im struct drinne und kannst es nach belieben bearbeiten.

    mfg hohesC



  • hohesC schrieb:

    ja!
    mit

    lseek(Datei,0L,SEEK_END);
    

    springst du ans ende der datei und schreibst dort weiter!

    mfg hohesC

    Wow, das ist ja der Hammer!
    Es funktioniert! Kann ich dem Prog mit lseek auch irgendwie sagen, dass er vom Anfang der Datei aus die Daten ausgeben soll? Sonst zeigt er mir immer nur den ersten Eintrag an.

    Danke für deine super Hilfe. Wieso gibt es eigentlich zum Öffnen, Schreiben und Lesen von Dateien so viele Möglichkeiten? 😕



  • guck mal eins über deinem post!
    das mit dem struckt array würde ich dir wie gesagt empfehlen, dann hast du sie wie schon erwähnt alle im struct und kannst nach belieben editieren.

    mfg hohesC


Anmelden zum Antworten