# Binär einlesen/auslesen(fread, fwrite)



## Googlehupf (27. Januar 2012)

Hi zusammen,

ich habe hier ein Bsp-Programm das zeigt das erstellen einer .dat datei und dann mit fwrite das irgendwie binär in die datei ".dat" schreibt.

*
1. Was bedeutet der format ".dat"?

2. Was bringt es überhaupt Werte binär in ein file schreiben in meinem Fall?

3. Wenn ich die .dat nach dem compilieren mit Hilfe des Notpad++ öffne, dann steht da:
)NUL NUL NUL#HNUL NUL usw. Was bedeutet das? Das ist doch kein Binär.

4. fwrite() wandelt alle Zahlen auf den der Pointer actVal bzw. arrayValues zeigt in Binär um, oder wie funktioniert das genau?*

Hier das Programm:

```
//1. c-file(main)
#include <stdio.h>
#include <stdlib.h>
#include "compl.h"

#define MAX_STRLEN 20

void main()
{
  char filename[MAX_STRLEN]="daten.dat";
  int file_len = 20;
  FILE *outFile=NULL;
  complex* arrayValues=NULL;
  complex* actVal = NULL;
  int n=0;

  arrayValues=malloc(sizeof(complex)*file_len);
  if (arrayValues != NULL)
  {
    actVal=arrayValues;
    for(n=0; n<file_len; n++)
    {
      actVal->real=rand();
      actVal->imag=rand();
		  c_print(*actVal);
      actVal++;
    }
    actVal=arrayValues;
    outFile=fopen(filename,"wb");   // wb = write binary siehe buch

    if (outFile != NULL) 
    {
			if (file_len != fwrite(arrayValues,sizeof(complex),file_len,outFile))
			{
				printf("error during write of %d blocks!\n",file_len);
			}
      fclose(outFile);
    }
		else
		{
			printf("cannot write file %s!",filename);

		}
    free(arrayValues);
  }
}

//2. c-file:
#include "compl.h"
#include <stdio.h>

void c_print(complex a)
{
  printf("%d + j%d\n",a.real,a.imag);
}

//h-file:
struct complex_struct
{
  int real;
  int imag;
};
typedef struct complex_struct complex;

void c_print(complex a);
```

Gruß 

Googlehupf


----------



## deepthroat (27. Januar 2012)

Hi.





Googlehupf hat gesagt.:


> 1. Was bedeutet der format ".dat"?


Nichts. Es ist eine beliebige Endung. "DATA"


Googlehupf hat gesagt.:


> 2. Was bringt es überhaupt Werte binär in ein file schreiben in meinem Fall?


Was ist denn dein Fall?


Googlehupf hat gesagt.:


> 3. Wenn ich die .dat nach dem compilieren mit Hilfe des Notpad++ öffne, dann steht da:
> )NUL NUL NUL#HNUL NUL usw. Was bedeutet das? Das ist doch kein Binär.


Alles auf dem Computer ist binär.

Der Editor zeigt aber natürlich Zeichen an und keine Bits.


Googlehupf hat gesagt.:


> 4. fwrite() wandelt alle Zahlen auf den der Pointer actVal bzw. arrayValues zeigt in Binär um, oder wie funktioniert das genau?


fwrite wandelt gar nichts um. Die Daten werden so wie sie im Speicher stehen in die Datei geschrieben, Byte für Byte.

Gruß


----------



## CPoly (27. Januar 2012)

Googlehupf hat gesagt.:


> 1. Was bedeutet der format ".dat"?



Nix weiter. Dateiendungen sind nur Kosmetik und ich nehme an, man wollte damit ausdrücken, dass es sich um rohe DATen handelt. ".dat"




Googlehupf hat gesagt.:


> 2. Was bringt es überhaupt Werte binär in ein file schreiben in meinem Fall?



Du kannst Sie mit fread einfach wieder einlesen. Du schreibst die Daten roh raus und ließt sie roh ein. Man muss sich keine Gedanken über irgendwelche Standards (xml etc.) machen.




Googlehupf hat gesagt.:


> 3. Wenn ich die .dat nach dem compilieren mit Hilfe des Notpad++ öffne, dann steht da:
> )NUL NUL NUL#HNUL NUL usw. Was bedeutet das? Das ist doch kein Binär.



Wieso ist das kein Binär? Notepad++ zeigt dir freundlicherweise auch \0 Bytes an, anstatt sie unsichtbar zu lassen. Denn im Zeichensatz gibt es dafür kein Zeichen. Es gibt außerdem kein nicht-Binär.




Googlehupf hat gesagt.:


> 4. fwrite() wandelt alle Zahlen auf den der Pointer actVal bzw. arrayValues zeigt in Binär um, oder wie funktioniert das genau?



Für jedes Byte wird ein Byte in die Datei geschrieben. Wenn du z.B. einen double Wert mit 64 Bit hast werden 8 Byte in die datei geschrieben, genau in der Reihenfolge, wie Sie im Speichern liegen. Mehr dazu hier http://en.wikipedia.org/wiki/IEEE_754-2008#Basic_formats und für das Beispiel hier http://en.wikipedia.org/wiki/Double...cision_binary_floating-point_format:_binary64 (siehe Bild)


----------



## Googlehupf (27. Januar 2012)

deepthroat hat gesagt.:


> Was ist denn dein Fall?



Ich soll ein Übungsprogramm schreiben das so in etwa aussehen soll:

```
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.

Entwerfen Sie ein Modul zur Verwaltung von Terminen.
Ein Termin muss folgendes enthalten:
Thema
von (Datum + Uhrzeit als Typ) 
bis (Datum + Uhrzeit als Typ)
Teilnehmer
Prioritaet  (HOCH, MITTEL, NIEDRIG)
Beschreibung
Status (ERLEDIGT, OFFEN)

Schreiben sie ein kleines Menue zum Verwalten der Termine.
Folgende Punkte muessen enthalten sein: Eingabe, Ausgabe eines 
Termines oder der gesamten Liste. Loeschen und Anfuegen von Terminen.
Die Termine sollen in einem Binaerfile gespeichert werden.
Termine sollen geloescht werden koennen und 
als erledigt markiert werden koennen.
```

Ja in diesem Fall muss ich binäres File io üben, aber was hat das mit Termindaten zu tun? Ich soll also ein Menü schreiben zum Verwalten der Termine etc.

Die Termine sollen in ein Binärfile gespeichert werden. Ja und mit "wb" schreibe ich binär in ein file korrekt?

Ich weis halt nicht wie ich da anfangen könnte, ich schätze mal vieles mit scanf zum Eingeben der Termine, Priorität etc.

Aber wie gesagt ich weiß gar nicht wie ich da Anfangen soll .

Kann mir da wer weiterhelfen bitte?


----------



## deepthroat (27. Januar 2012)

Googlehupf hat gesagt.:


> Ja in diesem Fall muss ich binäres File io üben, aber was hat das mit Termindaten zu tun?


Es ist ein Übungsprogramm. Irgendwie muss man die Daten ja speichern. Es soll kein Textformat sein, sondern ein binäres Format.


Googlehupf hat gesagt.:


> Die Termine sollen in ein Binärfile gespeichert werden. Ja und mit "wb" schreibe ich binär in ein file korrekt?


Nicht ganz. Die Datei wird im Binärmodus (im Gegensatz zum Textmodus) geöffnet. D.h. einfach nur, dass keine Übersetzung von \n in \r\n und zurück unter Windows gemacht wird. Ansonsten gibt's keinen Unterschied.

Das eigentlich "binäre" Schreiben geschieht mit fwrite (im Gegensatz zu fprintf, welches Text schreibt).


Googlehupf hat gesagt.:


> Ich weis halt nicht wie ich da anfangen könnte, ich schätze mal vieles mit scanf zum Eingeben der Termine, Priorität etc.


Ja, Benutzerinterface, Daten abfragen usw.

Dann Datenhaltung, speichern von Terminen usw.


Googlehupf hat gesagt.:


> Aber wie gesagt ich weiß gar nicht wie ich da Anfangen soll .


Eine Struktur für einen Termin wäre ein guter Anfang.

Dann versuch diese Struktur (bzw. mehrere davon) in eine Datei zu schreiben.

Dann wieder auslesen.

Damit bist du schonmal für's Wochenende beschäftigt...  

Gruß


----------



## Googlehupf (28. Januar 2012)

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 mehr Tipps geben ?


----------



## sheel (28. Januar 2012)

Googlehupf hat gesagt.:


> Sicher das das nicht komplezierter ist oder täuscht das?


Ja, sicher..

Statt die ganzen einzelnen Teile der Struktur einzeln mit fprintf/fscanf
in die Datei zu schreiben/daraus zu lesen braucht man für die ganze struct
nur ein fwrite/fread.

Ein "Nachteil" ist dann eben, dass die Datei nicht wirklich lesbar ist.
Falls das sein muss gehts mit den Funktionen nicht, ist ja aber nicht gefragt.

Gibt noch einige potenzielle Probleme, die hier aber nicht auftreten werden.
Betrifft vor allem Compiler-/Plattformwechsel.


Und zur Funktions-/Dateiaufteilung:
Wenn das ganze Programm nicht mehr macht als einlesen/speichern/laden
würd ich mir das gar nicht überlegen, sondern einfach alles ins main...

Wenn man unbedingt will, eben das Einlesen von der Tastatur.
struct im main per Pointer übergeben und in der Funktion befüllen.

Andere Aufteilungen verkomplizieren das nur unnötig.

Gruß


----------



## Googlehupf (28. Januar 2012)

Danke dir!

Welcher Sinn steckt den dahinter bei dieser Übung? Was soll/kann ich mit dem Binär fall oder im demfall mit dem verschiedenen Zeichen(1 Zeichen = 1 Byte) die in der .dat datei stehn machen?


----------



## sheel (28. Januar 2012)

Wieder auslesen?
Tieferen Sinn gibts bei einer Übung wohl nicht...


----------



## FSA (28. Januar 2012)

Ich habe das mit strukturen gemacht. Sry wenn er das auch gemacht hat habe es nur überflogen  Also ich speicher so immer meine "SaveGames" vom Spiel. Also Position, Blickrichtung, Objekte, Lebensenergie, usw. Das ist einfacherer als alles in einzelnen Werten reinzuschreiben


----------



## Googlehupf (29. Januar 2012)

Danke!

Ahja, und in diesem Ordner wo die Angabe(uebung.c) ist, ist noch eine Datei drinnen...
"._uebung.c"(<--- ist sozusagen transparent) heißt die und wenn ich diese öffne, dann erscheinen komische Zeichen(âœ      œ   ). Da steht irgendwas mit apple drinnen macOx textcoding apple.com etc. . 
Der Lehrer hat auch einen Mac-Laptop. Ist die Datei wichtig für die Übung?


----------



## sheel (29. Januar 2012)

Hellsehen können wir nicht, aber ich sag mal nein.


----------



## FSA (29. Januar 2012)

Also mit Transparent meinst du vll Unsichtbar? Also guck mal ob die Datei noch da ist wenn du deine IDE wieder schliesßt. Vll ist es nur eine Auslagerungsdatei.


----------



## Googlehupf (29. Januar 2012)

Ist noch immer da, aber glaub ist egal... Habs einfach vom Projekt ausgeschlossen.

Auf jedenfall hab ich jetzt angefangen diese Übung zu programmieren und es treten Fehler auf, die ich nicht finden kann:

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:siehe Bild

Jetzt mal abgesehn von den Fehlern passt es den in etwa so wie ich es programmiert habe?


```
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=(terminData*)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
```


----------



## sheel (29. Januar 2012)

Hi

da ist nichts "ohne Debugging"
Du bist nach wie vor im Debugmodus.

Hab mir nicht alles angeschaut, hast aber komische Pointersachen da drin.

write_termin:
Du allokierst etwas für daten, in daten1 ist derweil NULL.
Dann überschreibst du daten mit daten1.
Ergebnis: Beide sind NULL.
Dann verwendest du daten...

Vllt. solltest du sinnvollere Variablennamen geben?

Und im main freigeben, was wo anders angelegt wurde, ist unschön.


----------



## Googlehupf (29. Januar 2012)

sheel hat gesagt.:


> da ist nichts "ohne Debugging"
> Du bist nach wie vor im Debugmodus.



Mh ok, ich habs nur so geschrieben da es beim Visual c++ 2008 auch so steht, aber ok egal.



> write_termin:
> Du allokierst etwas für daten, in daten1 ist derweil NULL.
> Dann überschreibst du daten mit daten1.
> Ergebnis: Beide sind NULL.
> ...



Ok, hier hab ich einfach den 1. Wert wo "daten" daraufzeigt in daten1 zwischengespeichert, denn man muss ja ab den 1. Wert wo der Zeiger draufzeigt freigeben.

Und daten1 zeigt ja sowieso auf die gleichen Adresssen wie daten, denn es gibt ja nur ein "Reihe von Adressen" oder?

Zum scanf: scanf brauch ich eigentlich gar nicht da ich ja leerzeichen mit einlesen will...

Darum gets, aber dann kommt halt, die im Bild beschriebene Fehlermeldung.


----------



## sheel (29. Januar 2012)

Was in VS steht bedeutet, dass du das Programm nicht über den Debugger startest.
Kompiliert ist es aber dafür, sonst kommt nicht so eine Meldung.

Zum Rest: Keine Ahnung, was du da meinst.
Ich bleib dabei, dass du Unsinn mit deinen Pointern machst.

Beispiel

```
int a = 0;
int b = 0;

a = 123;
a = b;
```
Was steht jetzt in a und b?
0 und 0.

Zu "eine Reihe von Adresse":
Nö.  Speicherverwaltung von Windows/Linux macht da nicht mit.

Mach ein Programm, das eine Zahl in ein int einliest
und dann Zahl und Adresse davon ausgibt.
Starte dieses Programm zweimal und gib verschiedene Zahlen ein.

Die ausgegeben Zahlen sind bei jedem Programm anders,
die Adresse wird aber gleich sein.


----------



## Googlehupf (29. Januar 2012)

Ah ok, verstehe danke.

Ich hab nun die Zuweisung von daten und daten1 vertauscht jetzt kann man eingeben nur Problem ist... das 1. gets wird übersprungen warum?

Hättest du eine Idee wie ich die "Speicherstellen" im string so begrenze kann, dass ich im notpad++, wenn ich die .dat datei öffne nicht mehr die komischen I's sehe?


----------



## sheel (29. Januar 2012)

gets sind jetzt also wieder entkommentiert?
Bitte aktuellen Code.

Zu den Zeichen in Notepad:
So arbeiten fwrite/fread nun mal.
Einen Byteblock fixer Länge schreiben. Wenn der String nicht voll ist,
wird der Rest auch geschrieben.

Du könntest die Stringlänge als int vor dem String reinschreiben,
dann eben nur den tatsächlichen Inhalt,
und beim Auslesen über die Stringlänge eben feststellen,
wie viel gelesen werden muss.

Ganze struct in einem Befehl geht dann aber nicht mehr.


----------



## Googlehupf (29. Januar 2012)

Ok, aktueller Code hier(mit gets, jup, aber das 1. gets wird irgendwie ignoriert und in topic einfach nichts drinnen, aber wenn cih am anfang 2 termine eingebe und beim 2. durchlauf also beim 2. termin da kann ich jetzt das topic eingeben):


```
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=(terminData*)malloc(sizeof(terminData)* anz);
	if(daten != NULL)
	{
		daten1=daten;
		while(n<anz)
		{
			printf("Thema des Termins:\n");
			gets(daten1->topic);// hier "überspringt" er

			printf("Anfangsdatum des Termins:\n");
			gets(daten1->start_date);

			printf("Enddatum des Termins:\n");
			gets(daten1->end_date);
			
			printf("Wer nimmt teil?\n");
			gets(daten1->user);
			
			printf("Priorität des Termins(HOCH, MITTEL, NIEDRIG:\n");
			gets(daten1->priorität);
	    
			printf("Beschreibung des Termins:\n");
			gets(daten1->description);
	    
			printf("Status des Termins(ERLEDIGT, OFFEN):\n");
			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
```


----------



## sheel (29. Januar 2012)

Das ist, weil sich scanf und gets nicht vertragen.

Nimm die Funktion dazu:

```
int File::readint()
{
	int i;
	char buffer[20];
	if(NULL == fgets(buffer, 20, stdin))
		return -1;
	i = strlen(buffer) - 1;
	if(i >= 0 && buffer[i] == '\n')
		buffer[i] = '\0';
	else
	{
		while(fgetc(stdin) != '\n');
	}
	if(1 != sscanf(buffer, "%d", &i))
		return -1;
	return i;
}
```
und schreib statt dem scanf für anz im main das:

```
anz = readint();
```

Gruß


----------



## Googlehupf (5. Februar 2012)

Danke!

Ich hab jetzt alle Aufgaben erfüllt bis auf das Löschen eines Termins.

Folgendes hab ich mir gedacht:
Ich lese aus dem binär file aus, gebe das Thema 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 auf position 3 geschrieben und der 5. Termin auf Position 4 -> 1245

Was ist dann mit der 5. Position da bleibt doch eine Kopie vom 5. Termin erhalten oder?

Ein Problem tritt auch auf, wenn ich den 5. Termin löschen will wie mache ich das? Da kann ich ja nichts überscheiben oder?

Hier mein Versuch:

```
void termin_löschen(char filename[])
{
	FILE* outFile=NULL;
  FILE* inFile=NULL;

  termine* termindata=NULL;
	termine* hilf=NULL;
  termine thema;

	int anz=0;

  anz=file_len(filename);//hier wird die Anzahl der Termine die im File stehn ermittelt --> anz=Anzahl der Termine

	termindata=(termine *)malloc(sizeof(termine)*anz);
	if(termindata != NULL)
	{
		hilf=termindata;
	  outFile=fopen(filename,"rb");
		if(outFile == NULL)
		{
			printf("The files %s could not be opened",filename);
			exit(-1);
		}
	  
		fread(termindata,sizeof(termine),anz,outFile);

		fclose(outFile);

		inFile=fopen(filename,"wb");
		if(inFile == NULL)
		{
		  printf("The file %s could not be opened!");
			exit(-1);
		}

		printf("Geben Sie das Thema des Termins ein, der geloescht werden soll:")
		scanf("%s",thema.thema);

		for(x=0; x<anz; x++)
		{
		  if(thema.thema == termindata->thema)
			{
				//hier werden halt die ganzen Termine verschoben bzw. eine Schleife ist auch noch notwendig, aber ich kanns einfach nicht umsetzen...
			}
			termindata++;
		}

		free(hilf);
	}
	else
	{
	  printf("Memory allocation failure!");
	}
}
```


----------



## deepthroat (5. Februar 2012)

Hi.

Du solltest einfach die Termine aus der Datei in den Speicher laden.

Manipuliere die Termine im Speicher und schreibe die Termine komplett neu in die Datei (alte Datei überschreiben).

\edit: Eine Liste würde sich für die Verwaltung der Termine im Speicher vermutlich am besten eignen. Zumal es eine ziemlich simple Datenstruktur ist.

Gruß


----------



## sheel (5. Februar 2012)

Hi

zuerst was Anderes: Bei deiner Löschfunktion musst du nach
Einlesen und Löschen die Datei auch wieder beschreiben.
Sonst ists ja sinnlos, wenn der zu löschende Termin in der Datei noch existiert.

Zum Löschen selber: Du denkst richtig.
Aus einem Array "gelöscht" wird, in dem man alles
nach dem betroffenen Element eins nach vorne verschiebt/kopiert.

Dass es vom Letzten dann zwei gibt ist auch richtig, aber:
Ignorier das Gesamt-Letzte einfach.
Du liest 5 Elemente ein, 12345
Du löscht 3, ergib 12455.
Du weißt aber, dass es jetzt nur noch 4 Elemente sind,
und schreibst nur 4 wieder in die Datei.
1245.

Zum Löschen des Letzten:
Geht eigentlich genau so, es gibt dahinter nur nichts,
das verschoben/kopiert werden kann.
Da man das Verschieben in einer Schleife macht, von x bis Ende,
und Ende dann eben sofort ist, braucht es keine Sonderbehandlung.


----------



## Googlehupf (5. Februar 2012)

Danke, ich habs nun aber ein bisschen anders probiert, weil ich das mit dem schieben nicht wirklich hinbekommen habe.

Ich geb ein Thema ein z.B. "lernen", die if-anweisung wird voll ignoriert warum?

```
void termin_löschen(char filename[])
{
	FILE* outFile=NULL;
  FILE* inFile=NULL;

  termine* termindata = NULL;
	termine* hilf = NULL;
  char thema[100];

	int x=0;
	int anz=0;

	anz=file_len(filename);

	fflush(stdin);
	printf("Geben Sie das Thema des Termins ein, der geloescht werden soll:");
	gets(thema);

	termindata=(termine *)malloc(sizeof(termine)* anz);
  if(termindata != NULL)
	{
		hilf=termindata;
		outFile=fopen(filename,"rb");
		if(outFile == NULL)
		{
			printf("The file %s could not be opened",filename);
		}

		fread(termindata,sizeof(termine),anz,outFile);

		fclose(outFile);

		inFile=fopen(filename,"wb");
		if(inFile == NULL)
		{
			printf("The file %s could not be opened",filename);
		}

		for(x=0; x<anz; x++)
		{
		  if(thema != termindata->thema)
			{
			  fwrite(termindata,sizeof(termine),1,inFile);
			}
			termindata++;
		}

		fclose(inFile);
	}
	else
	{
	  printf("Memory allocation failure!");
	}

	free(hilf);
}
```


----------



## sheel (5. Februar 2012)

So, mit dem Sofort-Schreiben, gehts natürlich auch.
Der Fehler: char-Array-Strings werden mit strcmp verglichen.

Du vergleichst da, ob es die selben Strings sind
(nicht nur der gleiche Inhalt, sondern wirklich ein- und derselbe String).
Zum Inhaltsvergleich:

```
if(strcmp(thema, termindata->thema))
```


----------



## Googlehupf (25. Februar 2012)

Die Aufgabe ist das man einen bestimmten Termin suchen muss im Binärfile und dann auslesen.
Meine Idee: Ich geben vorher das Datum ein und dann vergleiche ich das Datum mit den Datums im Binärfile wenn die gleich sind speichere ich sie in eine Adresse wo ein Pointer draufzeigt, da es ja mehrere Termine an einem Tag geben kann. Problem ist nur das ich 2mal fast den selben Vorgang mache und das ist nicht gut.

Hier mal der Ausschnitt:


```
termin* termin_search(char filename[])
{
  FILE* outFile=NULL;
	termin temp;
	timestamp dat_von;
	termin* term_gesucht=NULL;
	int anz=0;


	outFile=fopen(filename,"r+b");
	if(outFile == NULL)
	{
	  printf("File %s could not be opened!",filename);
		exit(-1);
	}
  
	printf("Geben Sie das Datum des/der gesuchten Termin(e) ein(TTMMJJ):");
	scanf("%d",dat_von.tag);
	scanf("%d",dat_von.mon);
	scanf("%d",dat_von.jahr);

  while(!feof(outFile))
	{
	  fread(&temp,sizeof(termin),1,outFile);

		if(temp.von.tag == dat_von.tag && temp.von.mon == dat_von.mon && temp.von.jahr == dat_von.jahr)
		{
		  anz++;
		}
	}

	rewind(outFile);

  term_gesucht=malloc(sizeof(termin)*anz);

	while(!feof(outFile))
	{
	  fread(&temp,sizeof(termin),1,outFile);

		if(temp.von.tag == dat_von.tag && temp.von.mon == dat_von.mon && temp.von.jahr == dat_von.jahr)
		{
		  //hier käme dann das lange zuweisen, aber das dauert ja ewig zum schreiben^^
		}
	}

	return(term_gesucht);
}
```


Hier die lange Struktur:


```
struct timestamp_struct
{
short jahr;
short mon;
short tag;
int min;
};
typedef struct timestamp_struct timestamp;

struct termin_struct
{
char thema[MAX_THEMALEN];
timestamp von;
timestamp bis;
char teilnehmer[MAX_TEILNEHMER];
short priority;
char beschreibung[MAX_BESCHR];
short status;
};
typedef struct termin_struct termin;
```

Natürlich könnte ich die gesuchten Termine auch gleich im Unterprogramm ausgeben, aber zum Ausgeben habe ich eine weitere Funktion, die ich dann im Hauptprogramm aufrufen werde.

Diese sieht so aus:

```
void termin_out(termin termin_zur_ausgabe)
{
printf("------------------\n");
printf("Termin: %s \nTeilnehmer %s \nprio %d \nBeschreibung: %s \nStatus %d\n",termin_zur_ausgabe.thema,termin_zur_ausgabe.teilnehmer,termin_zur_ausgabe.priority,termin_zur_ausgabe.beschreibung,termin_zur_ausgabe.status);
printf("------------------\n");
}
```


----------



## sheel (25. Februar 2012)

Du kannst die Ausgebe-Funktion doch auch aus dem "Unterprogramm" aufrufen.
main ist nicht die einzige Stelle, wo man FUnktionen aufufen kann.
Das kann ziemlich verschachtelt werden.


----------



## Googlehupf (25. Februar 2012)

Ok, danke aber ich kann trotzdem nicht die 2 gleichen schleifen umgehn. Wenn ich mit Pointer mach muss ich ja die anz wissen für malloc und wenn i mit Array mache dann muss ich auch irgendwie Größe wissen, da ich kann ja net einfach 100 elemente definieren oder so. Ja klar kann ich das aber ist doof irgendwie. Ist wie beim malloc einfach schreiben sizeof(termin)*100 oder?


----------



## sheel (25. Februar 2012)

Die Gesamtanzahl der Termine muss vorher bekannt sein.
Wenn du 100 nehmen würdest, wäre es ja trotzdem möglich,
101 Ergebnisse reinspeichern zu müssen...
Also, wenn nicht im Programm vorher schon gemacht, abzählen.

Bitte Netiquette 15 beachten.


----------



## Googlehupf (26. Februar 2012)

Danke und sorry ich hab mich falsch ausgedrückt und noch dazu nicht sehr verständlich .

Ok die Gesamtzahl der gesuchten Termine muss vorher klar sein das man speicher allokieren kann.

Dies mache ich ja mit dieser Schleife:

```
while(!feof(outFile))
	{
	  fread(&temp,sizeof(termin),1,outFile);

		if(temp.von.tag == dat_von.tag && temp.von.mon == dat_von.mon && temp.von.jahr == dat_von.jahr)
		{
		  anz++;
		}
	}
```

Und danach rufe ich wieder die gleiche Schleife auf nur halt zum Ausgeben:

```
while(!feof(outFile))
	{
	  fread(&temp,sizeof(termin),1,outFile);

		if(temp.von.tag == dat_von.tag && temp.von.mon == dat_von.mon && temp.von.jahr == dat_von.jahr)
		{
		   for(x=0; x<anz; x++)
                   {
                      termin_out(*(ges_termin+x));
                   }
		}
	}
```

Und ich möchte verhindern das ich 2mal die gleiche schleifen-funktion hintereinander verwende.
Kann ich das irgendwie umgehn/anders machen?


----------



## sheel (26. Februar 2012)

Also, zuerst mal:

```
*(ges_termin+z)
```
Warum nicht

```
ges_termin[z]
```

Dann...die for-Schleife mmit Inhalt im zweiten Costück gehört
eigentlich nach das komplette Codestück.
Dort, wo gerade das for steht, solltest du das Eingelesene doch ins Array speichern
(das zwischen Codeteil1 und 2 mit malloc angelegt wurde).

Dann, erst danach, kannst du mit for alle durchgehen und ausgeben.

Noch was: Nach dem ersten while(!feof)-Block musst du dem Programm sagen, die Datei wieder von vorn zu lesen, bevor der zweite while(!feof)-Block kommt:

```
fseek(outFile, 0L, SEEK_SET);
```
Oder du schließt und öffnest wieder (fclose-fopen). fseek ist aber schneller.

Noch was: Warm outFile? Wenn schon, dann inFile.


Zur Frage, ob man sich die zweite while-Schleife sparen kann:
Nein, nicht wenn du das Ganze mit Arrays machst.

Naja, eigentlich schon. Aber das wäre noch schlechter als der aktuelle Code
(Prinzip: zuerst ein Array Größe 1, einlesen. Wenns noch weiter geht, noch ein malloc für Größe 2, den Wert vom 1-Array reinkopieren, den neuen dazu, das 1-Array löschen.
Wenns in der Datei noch immer weiter geht, ein 3-Array machen...
aber das ist großer Blödsinn).

Alternative: Keine Array, sondern Listen verwenden.
Da muss die Gesamtgröße nicht schon von Anfang an bekannt sein.


----------

