Übung zum binärem Schreiben
-
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:
-
Hab was vergessen:
* Kurzbeschreibung : Programm zum Ueben von dynamischer Speicherverwaltung, binaeren FileIO.
* Implementierung zum Test von malloc free
* Ueben von modularem Programmieren und ueben von Strukturen mit Pointern.
-
Ja und jetzt muss ich halt die ganzen Termine im binär file auslesen mit fread und so bzw. dann halt malloc verwenden, aber nur wie? hat einer ein paar Tipps bitte?
-
Arbeite erst mal alle dir hier gegebenen Tipps ab, bereinige dadurch deine Fehler und dann hilft dir hier vielleicht doch noch jemand weiter.
-
Jo danke, ich habs jetzt soweit hinbekommen jetzt muss ich nur noch einen Termin aus dem binär file löschen.
Ich hab folgende Idee: ich lese aus dem binär file aus, gebe das Thema & Datum des Termins ein der gelöscht werden soll, such den dann wenn ich die position gefunden habe vom Termin dann überschreibe ich diesen Termin mit dem nächsten usw.
Also ich hab 5 Termine und der 3. soll gelöscht werden...
12345 --> der 4. termin wird uaf position 3 geschrieben und der 5. auf 4 -> 1245
Soll ich das so machen?
Aber was ist wenn ich den 5. Termin löschen müsste? Wer überschreibt den dann?
-
Keiner.
-
Ja ok, was hälst du von meiner Idee bzw. wie löse ich das mit dem letzten Termin weis das einer bitte?
-
Dann ist deine Datei nach dem 4. Eintrag zu Ende.