Übung zum binärem Schreiben
-
tom1122 schrieb:
Ich dachte ich mache folgendes: eine struktur in dem das thema, datum, teilnehmer, priorität, Beschreibung und Status(erledigt, offen) des termines enthält und diese Struktur dann binär in ein file schreiben.
Was sagt ihr dazu?
Ja, das wird damit gemeint sein. Ist dir damit geholfen, oder hast du irgendwelche konkreten Probleme?
Wenn du übrigens richtig Eindruck schinden willst, kannst du Typen fester Breite benutzen, Padding vermeiden und den Endian normieren, damit deine Datei auf allen Plattformen benutzbar ist, aber ich gehe nicht davon aus, dass euer Lehrer damit rechnet - da werden Binärformate nämlich richtig haarig.
-
Ja ok, danke.
Angenommen ich ich habe jetzt schon diese ganze Struktur, wo das Datum, die Beschreibung, das Thema etc. drinnen steht.
Diese ganze Struktur soll ich nun binär in ein .dat file schreiben?
Dieses .dat file öffnen ich nun mit Notepad++ und dann sehe ich aber irgendwelche Zeichen aber keine "0 und 1".
1. Wie macht man die Nullen und Einsen sichtbar und 2. was kann ich dann damit tun und 3. was bringt das die ganzen Daten in ein Binärfile zu schreiben?
-
Die 0 und 1 sind die Bits. Die werden aber schon mal zu acht zusammen gefaßt als Byte.
Was du da siehst sind die Bytes. Allerdings als Zeichen. Jedes Zeichen steht für einen Bytewert.Kennst du ASCII?
Kennst du den Unterchied zwischen oder 49 und 0x31 oder 1 und '1' ?
-
Jup ASCII-Code kenne im C-Buch ist eine Tabelle dabei.
Aber die Unterschiede kenn ich net.
-
Ok, danke.
Aber klingt doch irgendwie einfach... alles mit Hilfe von scanf in eine Struktur reinlesen und die struktur dann in ein .dat file mit fwrite reinschreiben oder?
Sicher das das nicht komplezierter ist oder täuscht das?
Bzw. was ist mit Unterprogramme/Funktionen - Wo soll man den die hier nutzen.
Bis jetzt habe ich immer ein Unterprogramm/Funktion gebraucht, wenn ich was berechne oder so.
Aber hier habe ich keine blassen schimmer? Die ganze einlesungen in die Struktur vielleicht?
Und was ist mit Modulen - Wie viele C- und h-files?
Bis jetzt hab ich es immer so gemacht: 1 c-file für Hauptprogramm, 1 c-file fürs auslesen eines files(unterprogramm) und 1 c-file für die rechnungen(unterprogramm) und 2 h-files die jeweils zu den 2 c-files mit Unterprogrammen gehören.
Kann mir wer bitte Tipps geben ?
-
Ok, ich habs nun programmiert, nicht alles nur mal so angefangen.
Der Code ist hier: http://pastebin.com/ukcajiuM
Also, mein Problem:
Wenn ich das ganze mit scanf mache dann geschieht folgendes beim "Starten ohne Debugging": Ich kann och die anzahl der Termine eingeben und auch noch das Thema aber dann kommt: "'name des programms'.exe funktioniert nicht mehr".Wenn ich das ganze mit gets mache dann geschieht folgendes beim "Starten ohne Debugging": Hier kann ich auch noch die Anzahl eingeben aber dann kommt: http://www.imagebanana.com/view/fx5totc2/error.png
Was könnte es denn da haben?
Ahja und was sagt ihr dazu wie ich es programmiert habe?
Danke im voraus!
-
130 Zeilen kannst du auch hier posten, dann lesen das mehr Leute. Ich mache das mal für dich:
1. c-file(main): #include "write_termin.h" #include "w_binaer_file.h" #include <stdio.h> void main() { char filename[MAX_LEN]="daten.dat"; terminData* daten=NULL; int anz=0; printf("Geben Sie bitte die Anzahl Ihrer Termine ein:"); scanf("%d",&anz); daten=write_termin(filename,anz); write_binaer_file(filename,daten,anz); free(daten); } 2. c-file: #include "write_termin.h" #include <stdio.h> terminData* write_termin(char filename[], int anz) { terminData* daten=NULL; terminData* daten1=NULL; int n=0; daten=malloc(sizeof(terminData)* anz); if(daten != NULL) { daten=daten1; while(n<anz) { printf("Thema des Termins:\n"); scanf("%s",&daten1->topic); //gets(daten1->topic); printf("Anfangsdatum des Termins:\n"); scanf("%s",&daten1->start_date); //gets(daten1->start_date); printf("Enddatum des Termins:\n"); scanf("%s",&daten1->end_date); //gets(daten1->end_date); printf("Wer nimmt teil?\n"); scanf("%s",&daten1->user); //gets(daten1->user); printf("Priorität des Termins(HOCH, MITTEL, NIEDRIG:\n"); scanf("%s",&daten1->priorität); //gets(daten1->priorität); printf("Beschreibung des Termins:\n"); scanf("%s",&daten1->description); //gets(daten1->description); printf("Status des Termins(ERLEDIGT, OFFEN):\n"); scanf("%s",&daten1->start_date); //gets(daten1->start_date); n++; daten1++; } } else { printf("Memory allocation Failure!"); } return(daten); } 3. c-file: #include "write_termin.h" #include "w_binaer_file.h" #include <stdio.h> void write_binaer_file(char filename[],terminData* termindaten, int anz) { FILE* outFile=NULL; outFile=fopen(filename,"wb"); if(outFile != NULL) { if(anz != fwrite(termindaten,sizeof(terminData),anz,outFile)) { printf("error during write of %d blocks",anz); } } else { printf("File %s could not be opened",filename); } fclose(outFile); } 1. h-file: #ifndef _write_termin_h_ #define _write_termin_h_ 1 #define MAX_LEN 100 struct struct_termin { char topic[MAX_LEN]; char start_date[MAX_LEN]; char end_date[MAX_LEN]; char user[MAX_LEN]; char priorität[MAX_LEN]; char description[MAX_LEN]; char state[MAX_LEN]; }; typedef struct struct_termin terminData; terminData* write_termin(char filename[], int anz); #endif 2. h-file: #include "write_termin.h" #ifndef _wbinaer_file_h_ #define _wbinaer_file_h_ 1 void write_binaer_file(char filename[],terminData* termindaten, int anz); #endif
-
scanf("%s",&daten1->topic);
liest nur bis zum ersten Whitespace (Leerzeichen, Tabulator, Entertaste) und bei Strings kommt da kein & hin.
Zudem solltest du die Länge begrenzen.
-
1. Sonderzeichen in Bezeichnern sind allgemein nicht erlaubt.
2. Für malloc sollte man stdlib.h einbinden
3. Der Fehler bei scanf wurde dir schon genannt. Ich gehe mal im weiteren von der gets-Version aus.
4. gets sollte man nicht benutzen. Nimm fgets mit Obergrenze und stdin als Quelle.
5. Rückgabetyp von main ist int, nicht void.
6. filename in write_termin wird nie benutzt. Wirft kein gutes Licht auf dein Programm, wenn noch solche Sachen drin sind.7. Die obigen 6 Punkte hätte dir auch dein Compiler sagen können, denn ich habe sie gefunden, indem ich meinen Compiler gefragt habe, was er von deinem Programm hält. Nun kann noch eine Analyse durch einen Debugger folgen:
8. Der Absturz erfolgt in Zeile 59, daten1 hat den Wert 0. Kein Wunder, denn kurz davor sehen wirterminData* daten1=NULL;
und das ändert sich auch nie. Du meintest wohldaten
statt das überflüssigedaten1
. Chaotischer Stil führt zu Fehlern.
9. Ich korrigiere das mal alles auf daten statt daten1:
10. Läuft soweit, bis anderer Fehler auftritt. Debugger sagt das free am Ende macht Probleme. Hier sieht man auf den ersten Blick keinen Fehler. Werfe automatischen Speicherdebugger (valgrind) an:
11. Im fwrite wird über das Array hinaus gelesen. das ist auch merkwürdig, genauso wie der Fehler beim free. Muss wohl doch mal ein Mensch ran und sich das näher anschauen:
12. Aha, als ich alles aufdaten
statt daten1 umgeschrieben habe, habe ich nicht beachtet, dass der Pointer hochgezählt wird. Du warst also schon auf dem richtigen Weg, dir das Original zu merken, hast es nur falschrum gemacht. Mache es richtig rum. (Ich wurde aber eigentlich eine for-Schleife und Arraydereferenzierung benutzen, aber so ist es näher an deinem alten Programm).
13. Funktioniert.
14. Zur Sicherheit nochmal valgrind drüber laufen lassen:
15. Beschwert sich noch, dass die rausgeschriebenen Bytes nicht initialisiert sind. Was auch kein Wunder ist, sie sind nicht initalisiert, weil malloc uninitialisierten Speicher zurück gibt. Das heißt, da wird aus deinen char-Arrays auch noch uninitialisierter Unsinn, der hinter den eingegebenen Strings steht, in die Datei geschrieben. Nehme statt malloc calloc.
16. Fehlerfrei.Und dabei habe ich bis auf Punkt 12 die ganze Zeit bequem im Sessel gesessen und alles den Computer machen lassen
.
-
Ist ja cool
Ich danke euch! Wo sieht man den die Compiler-Warnungen und was ist valgrind(<--soll ich googeln?)?
-
tom1122 schrieb:
Wo sieht man den die Compiler-Warnungen ..
Da wo auch die Fehler stehen.
tom1122 schrieb:
... und was ist valgrind(<--soll ich googeln?)?
DreimalEinmal darfst du raten.
Obwohl (IMHO) bei solchen Sachen die Wikipedia (auch die Englische nicht vergessen) einen besseren Überblick vermittelt.
-
Danke.
Wenn ich nun Termine suche an einem bestimmten Datum... soll ich diese dann ausgeben.
Übung der Aufgabe ist ja malloc/free wie kann ich das mit malloc lösen?
Hier mal mein bis jetzt angefertigets Programm(bei der funktion eingabe ist malloc umsosnt eig., aber das nun egal es geht um 'ausgabe_termin'):
h-file: #ifndef _termine_h_ #define _termine_h_ #define MAX_STRLEN 40 struct tdatum_struct { int datum; float uhrzeit; }; typedef struct tdatum_struct tdatum; struct termine_struct { char thema[MAX_STRLEN]; tdatum von; tdatum bis; char teilnehmer[MAX_STRLEN]; char prioritaet[MAX_STRLEN]; char beschreibung[MAX_STRLEN]; char status[MAX_STRLEN]; }; typedef struct termine_struct termine; void eingabe(char filename); void ausgabe_termin(char filename); #endif 1.c-file: #include <stdio.h> #include "termine.h" #include <string.h> void eingabe(char filename[]) { FILE *outfile=NULL; termine *terminPointer=NULL; termine *temp=NULL; terminPointer=malloc(sizeof(termine)); if(terminPointer != NULL) { temp=terminPointer; fflush(stdin); printf("Thema des Termins:\n"); gets(temp->thema); printf("Termin von:\n"); printf("Datum(TTMMJJ):\n"); scanf("%d",&temp->von.datum); fflush(stdin); printf("Uhrzeit(HH.MM):\n"); scanf("%f",&temp->von.uhrzeit); fflush(stdin); printf("Termin bis:\n"); printf("Datum(TTMMJJ):\n"); scanf("%d",&temp->bis.datum); fflush(stdin); printf("Uhrzeit(HH.MM):\n"); scanf("%f",&temp->bis.uhrzeit); fflush(stdin); printf("Teilnehmer:\n"); gets(temp->teilnehmer); printf("Prioritaet des Termins(HOCH, MITTEL, NIEDRIG):\n"); gets(temp->prioritaet); printf("Beschreibung des Termins:\n"); gets(temp->beschreibung); strcpy(temp->status,"OFFEN"); printf("\n"); printf("\n"); } else { printf("Memory allocation Failure!"); } outfile=fopen(filename,"ab"); if (outfile != NULL) { if (1 != fwrite(terminPointer,sizeof(termine),1,outfile)) { printf("error during write of 1 blocks!\n"); } //fwrite(terminPointer,sizeof(termine),1,outfile); fclose(outfile); } else { printf("cannot write file %s!",filename); } free(terminPointer); } void ausgabe_termin(char filename[]) { FILE*infile=NULL; termine *terminPointer=NULL; tdatum *temp=NULL; printf("Geben Sie das Datum des suchenden Termins ein:"); scanf("%d",&temp->datum); infile = fopen(filename,"rb"); terminPointer=malloc(sizeof(termine)*anz); //anz sollte die Anzahl der vorhandenen Termine sein, die das oben eingegebene Datum besitzen - Die Frage ist halt jetzt wie ich die Anzahl bekomme. if(terminPointer != NULL) { while(!feof(infile)) { fread(terminPointer,sizeof(termine),anz,infile); if(temp->thema == terminPointer->thema) { printf("%s\n%s\n",terminPointer->thema,terminPointer->beschreibung); printf("Von %d um %d Uhr ",terminPointer->von.datum,terminPointer->von.uhrzeit); printf("bis %d um %d Uhr \n",terminPointer->bis.datum,terminPointer->bis.uhrzeit); printf("Teilnehmer: %d\n",terminPointer->teilnehmer); printf("Prioritaet: %s\n",terminPointer->prioritaet); printf("Status: %s\n\n",terminPointer->status); } } } else { printf("Memory allocation failure!"); } free(terminPointer); free(temp); fclose(infile); } 2. c-file(main): #include<stdio.h> #include "termine.h" void main() { char filename[MAX_STRLEN]="daten.dat"; int x=0; printf("Geben Sie 1 ein um einen Termin einzugeben.\n"); printf("Geben Sie 2 ein um einen Termin auszugeben.\n"); printf("Geben Sie 3 ein um die ganze Terminliste auszugeben.\n"); printf("Geben Sie 4 ein um einen Termin zu loeschen.\n"); printf("Geben Sie 5 ein um einen Termin anzufuegen.\n"); printf("\n"); printf("Auswahl:"); scanf("%d",&x); switch(x) { case 1: eingabe(filename); break; case 2: ausgabe_termin(filename); break; case 3: break; case 4: break; case 5: break; default: printf("Fehler beim Eingeben!\n"); break; } }
-
Bei Übungen zu malloc/free denke ich an eine andere Struktur
#define MAX_STRLEN 40 // nicht nötig struct tdatum_struct { int datum; float uhrzeit; }; typedef struct tdatum_struct tdatum; struct termine_struct { char *thema; // Speicher per malloc besorgen tdatum von; tdatum bis; char *teilnehmer; //dto. char *prioritaet; //dto. char *beschreibung; //dto. char *status; //dto. };
-
Und sicher das man in der funktion ausgabe_termin kein "malloc" anwenden kann?
-
Warum? Du musst doch nur die Daten ausgeben.
-
Ok, aber ich muss auch die gesamte Terminliste ausgeben, d.h. alles was im binärfile drinnen soll ich ausgeben... und der lehrer hat gesagt ich muss malloc dazu benutzen... aber wie?
zum anfügen von Terminen: reicht das den so mit der funktion "eingabe"?
-
Wieviel Termine kannst du denn verwalten?
-
Das ist ne gute Frage keine Ahnung... wurde nicht bekannt gegeben.
der lehrer hat auch erwähnt: die Gesamtebyteanzahl des files dividieren durch die Byteanzahl der Struktur = Anzahl der Termine...
und dann kann man da: pointer=malloc(sizeof(struct)*anzahl) schreiben..
Aber wie soll man den das genau machen?
Der aktuelle code ist:
h-file: #ifndef _termine_h_ #define _termine_h_ #define MAX_STRLEN 40 struct tdatum_struct { int datum; float uhrzeit; }; typedef struct tdatum_struct tdatum; struct termine_struct { char thema[MAX_STRLEN]; tdatum von; tdatum bis; char teilnehmer[MAX_STRLEN]; char prioritaet[MAX_STRLEN]; char beschreibung[MAX_STRLEN]; char status[MAX_STRLEN]; }; typedef struct termine_struct termine; void eingabe(char filename); void ausgabe_termin(char filename); #endif 1.c-file: #include <stdio.h> #include "termine.h" #include <string.h> void eingabe(char filename[],int anz) { FILE *outfile=NULL; //termine *terminPointer=NULL; termine temp; fflush(stdin); printf("Thema des Termins:\n"); gets(temp.thema); printf("Termin von:\n"); printf("Datum(TTMMJJ):\n"); scanf("%d",&temp.von.datum); fflush(stdin); printf("Uhrzeit(HH.MM):\n"); scanf("%f",&temp.von.uhrzeit); fflush(stdin); printf("Termin bis:\n"); printf("Datum(TTMMJJ):\n"); scanf("%d",&temp.bis.datum); fflush(stdin); printf("Uhrzeit(HH.MM):\n"); scanf("%f",&temp.bis.uhrzeit); fflush(stdin); printf("Teilnehmer:\n"); gets(temp.teilnehmer); printf("Prioritaet des Termins(HOCH, MITTEL, NIEDRIG):\n"); gets(temp.prioritaet); printf("Beschreibung des Termins:\n"); gets(temp.beschreibung); strcpy(temp.status,"OFFEN"); printf("\n"); printf("\n"); outfile=fopen(filename,"ab"); if (outfile != NULL) { if (1 != fwrite(&temp,sizeof(termine),1,outfile)) { printf("error during write of 1 blocks!\n"); } //fwrite(terminPointer,sizeof(termine),1,outfile); fclose(outfile); } else { printf("cannot write file %s!",filename); } } void ausgabe_termin(char filename[]) { FILE*infile=NULL; termine terminPointer; tdatum temp = {0,0.0}; int anz=0; printf("Geben Sie das Datum des suchenden Termins ein: "); scanf("%d",&temp.datum); infile = fopen(filename,"rb"); while(!feof(infile)) { fread(&terminPointer,sizeof(termine),1,infile); if(terminPointer.von.datum == temp.datum) { printf("%s\n%s\n",terminPointer.thema,terminPointer.beschreibung); printf("Von %d um %d Uhr ",terminPointer.von.datum,terminPointer.von.uhrzeit); printf("bis %d um %d Uhr \n",terminPointer.bis.datum,terminPointer.bis.uhrzeit); printf("Teilnehmer: %d\n",terminPointer.teilnehmer); printf("Prioritaet: %s\n",terminPointer.prioritaet); printf("Status: %s\n\n",terminPointer.status); } } fclose(infile); } 2. c-file(main): #include<stdio.h> #include "termine.h" void main() { char filename[MAX_STRLEN]="daten.dat"; int x=0; printf("Geben Sie 1 ein um einen Termin einzugeben.\n"); printf("Geben Sie 2 ein um einen Termin auszugeben.\n"); printf("Geben Sie 3 ein um die ganze Terminliste auszugeben.\n"); printf("Geben Sie 4 ein um einen Termin zu loeschen.\n"); printf("Geben Sie 5 ein um einen Termin anzufuegen.\n"); printf("\n"); printf("Auswahl:"); scanf("%d",&x); switch(x) { case 1: eingabe(filename); break; case 2: ausgabe_termin(filename); break; case 3: break; case 4: break; case 5: break; default: printf("Fehler beim Eingeben!\n"); break; } }
-
Oder habt ihr gerade verkettete Listen im Plan?
-
Nein, sowas haben wir nocht nicht gelernt.
Nochmal die Aufgabenstellung: