staging.inyokaproject.org

Problem in C - Segmentation Fault: 11

Status: Ungelöst | Ubuntu-Version: Ubuntu 17.10 (Artful Aardvark)
Antworten |

gingerP

Anmeldungsdatum:
11. Januar 2018

Beiträge: Zähle...

Hallo ihr Lieben, ich muss für die Uni ein Programm erstellen. Nun bekomme ich beim Ausführen direkt ein Segmentation Fault:11. Könnt ihr mir sagen, woran das liegen könnte? Danke schonmal.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
// tarifliste wird nicht richtig abgelesen!!!
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define clear() system("clear") //muss am Anfangs hinzugefuegt werdens


//Feld fuer die gespeicherte Daten
// char kontrolle1 = 'A'; //fuer die Namen, damit sie laenger als 1 Buchstabe sind
// char kontrolle2 = 'a';

struct datum
{
  int tag;
  int monat;
  int jahr;
};
struct dauer
{
  int minuten;
  int sekunden;
  int gesamt;
};
struct telefonat
{
  int name;
  int anfangsstunde;
  int anfangsminute;
  int entfernung;
  struct datum datum;
  struct dauer dauer;
  float preis;
  float gesamtpreis;
};

void gespraech(struct telefonat anruf[100], int *nummer);
void ablesen(struct telefonat anruf[100], int *nummer);
void loeschen(struct telefonat anruf[100], int *nummer);
void ausgeben(struct telefonat anruf[100], int *nummer, int name);
void monatsrechnung(struct telefonat anruf[100], int *nummer);
double einheiten(struct telefonat anruf[100],int anfangsstunde, int entfernung, int *nummer);
void monatsloeschen(struct telefonat anruf[100], int *nummer);
void puffer(); 
 
int main()
{
  struct telefonat anruf[100];
  int eingabe;  
  clear();
	FILE *feldlesen;
	FILE *feld_speichern;
	FILE *nummer_speichern;
FILE *nummerlesen;
	feldlesen =  fopen("liste.dat", "r");
	fread(anruf, sizeof(struct telefonat), 100, feldlesen);
	fclose(feldlesen);


int nummer;

	nummerlesen = fopen("nummer.dat", "r");
	fscanf(nummerlesen, "%d", &nummer);
	fclose(nummerlesen);



 do
 {
 	clear();
   printf("Willkommen im Menue!\n Was willst du machen:\n");
   printf("1 - Gespraech eingeben\n2 - Gespraeche anzeigen\n3 - Bestimmtes Gespraech loeschen\n4 - Gespraeche eines Monats loeschen\n5 - Monatsrechnung\n6 - Programm beenden\n");
   eingabe = -1;  
   scanf("%d", &eingabe);
   switch(eingabe)
   {
   case 1: 
    gespraech(anruf,&nummer); 
    break;
   case 2:
   ablesen(anruf, &nummer);
   printf("           Datum           Uhrzeit           Dauer (m:s)           Zone\n");
	printf("Anna:\n");
	ausgeben(anruf, &nummer,1);
	printf("Franz:\n");
	ausgeben(anruf, &nummer,2);
	printf("Lotta:\n");
	ausgeben(anruf, &nummer,3);
	printf("Chris:\n");
	ausgeben(anruf, &nummer,4);
	printf("Mark:\n");
	ausgeben(anruf, &nummer,5);
	printf("\nDu willst zurück ins Menue? Druecke ENTER!\n");
	puffer();
     break;
   case 3:
   ablesen(anruf, &nummer);
   printf("           Datum           Uhrzeit           Dauer (m:s)           Zone\n");
	printf("Anna:\n");
	ausgeben(anruf, &nummer,1);
	printf("Franz:\n");
	ausgeben(anruf, &nummer,2);
	printf("Lotta:\n");
	ausgeben(anruf, &nummer,3);
	printf("Chris:\n");
	ausgeben(anruf, &nummer,4);
	printf("Mark:\n");
	ausgeben(anruf, &nummer,5);
     loeschen(anruf, &nummer);
     puffer();
     break;
   case 4:
     monatsloeschen(anruf, &nummer);
     break;
   case 5:
     monatsrechnung(anruf, &nummer);
     break;
   case 6:
     break;
   default:
     printf("Die Eingabe ist falsch. Es soll eine ganze positive NUmmer eingegeben werden.\nVersuchen Sie noch mal.\n");
    }

	feld_speichern = fopen("liste.dat", "w");
	fwrite(anruf, sizeof(struct telefonat), 100, feld_speichern);
	fclose(feld_speichern);

	nummer_speichern = fopen("nummer.dat", "w");
	fprintf(nummer_speichern, "%p", &nummer);
	fclose(nummer_speichern);
 puffer();
 } while (eingabe != 6);
return 0;
}
/*die Daten fuer die Gespraeche werden vom Benutzer eingegeben*/
void gespraech(struct telefonat anruf[100], int *nummer)
{
int tag = -1 , monat = -1, jahr = 1, minuten = -1, sekunden = -1, entfernung = -1, anfagsstunde = -1, minute = -1;
 
printf("%d\n", *nummer);

do
{
    printf("Wer hat telefoniert? \n 1: Anna \n 2: Franz \n 3: Lotta \n 4: Chris \n 5: Mark \n");
    anruf[*nummer].name = -1; // Einlesen der Angaben
    scanf("%i", &anruf[*nummer].name);
    if (anruf[*nummer].name > 5 || anruf[*nummer].name < 0)
        printf("\nerror: Tipp: gib einen gueltigen Namen an.\n\n");
}while(anruf[*nummer].name > 5 || anruf[*nummer].name < 0);
puffer();
	

do
{
	printf("Tag eingeben:\n");
    scanf("%d", &tag);
    puffer();
}while((tag < 0 || tag > 31));

do
{
	printf("Monat eingeben:\n");
    scanf("%d", &monat);
    puffer();
}while((monat < 0 || monat > 12));

do
{
	printf("Jahr eingeben:\n");
    scanf("%d", &jahr);
    puffer();
}while((jahr < 1980 || jahr > 2017));

anruf[*nummer].datum.tag = tag;
anruf[*nummer].datum.monat = monat;
anruf[*nummer].datum.jahr = jahr;
    
do
{
	printf("Bitte Uhrzeit (hh:min) eingeben:\n");
    scanf("%d %d", &anfagsstunde, &minute);
    puffer();
}while((anfagsstunde < 0 || anfagsstunde > 24)&&(minute < 0));
    anruf[*nummer].anfangsstunde = anfagsstunde;
	anruf[*nummer].anfangsminute = minute;
do
{
	printf("Dauer in Minuten eingeben:\n");
    scanf("%d", &minuten);
    puffer();
}while((minuten < 0 || minuten > 1440));

do
{
	printf("Dauer in Sekunden eingeben:\n");
    scanf("%d", &sekunden);
    puffer();
}while((sekunden < 0 || sekunden > 60));
anruf[*nummer].dauer.minuten = minuten;
anruf[*nummer].dauer.sekunden = sekunden;
anruf[*nummer].dauer.gesamt = minuten * 60 + sekunden;
    
 do
{
   printf("Geben Sie die Entfernung ein:\n1: Ort\n2 :Fern\n3 :Ausland: ");
   scanf ("%i", &entfernung);
   puffer();
} while (entfernung < 1 || entfernung > 3);
    
    anruf[*nummer].entfernung = entfernung;

printf("\nDu willst zurück ins Menue? Druecke ENTER!\n");	
nummer++;
//nummer_speichern(nummer);
	
}
/*die Dateien werden abgelesen und auf die Konsole ausgegeben*/
void ablesen(struct telefonat anruf[100], int *nummer)
{		
	if (nummer == 0)
	{
		printf("Es sind keine Gespraeche vorhanden :(\n");
	}
	
}
/*puffer wird geleert*/
void puffer()
{
	char z;
		do 
		{
			z = getchar();
		}
		while( z != 10 );
}
/*hier wird ein Gespraech unter bestimmten Nummer geloescht*/
void loeschen(struct telefonat anruf[100], int *nummer)
{
int eingabe_nummer;
if (nummer == 0)
{ 
	printf("Es sind keine Gespreache  vorhanden :(\n");
}
do
{
	printf("Die Nummer des Gespraechs eingeben: ");
	scanf("%d", &eingabe_nummer);
}while(eingabe_nummer > *nummer);
		
do
{
	anruf[eingabe_nummer-1] = anruf[eingabe_nummer];
	eingabe_nummer++;
}while(eingabe_nummer <= *nummer);
	nummer--;
		
/*es werden die neue Gespraeche und die Nummer gespeichert*/
//nummer_speichern(nummer);
}
/*hier werden alle vorhandene Gespreache ausgegeben*/
void ausgeben(struct telefonat anruf[100], int *nummer, int name)
{
	int i;

	for(i=0; i < *nummer; i++)
{
if (anruf[i].name==name){ // i Eintraege sind die Platzierungen auf dem Array
printf("Nr.%2.0i     |" , i+1);
//printf("%i. Gespraech:  | ", j);
printf("%2.0i/%2.0i/%2.0i     | " , anruf[i].datum.tag, anruf[i].datum.monat, anruf[i].datum.jahr);
printf("%2.0i:%2.0i          | " , anruf[i].anfangsstunde,anruf[i].anfangsminute);
printf("%2.0i:%2.0i             | " , anruf[i].dauer.minuten, anruf[i].dauer.sekunden);
if (anruf[i].entfernung == 1 )
{
printf("Ortsgespraech");
}
if (anruf[i].entfernung == 2 )
{
printf("Ferngespraech");
}
if (anruf[i].entfernung == 3 )
{
printf("Auslandsgespraech");
}
printf("\n");
}
}
printf("\n");
}
/*hier kann man nach dem Monat bzw. nach den Namen suchen*/
void monatsrechnung(struct telefonat anruf[100], int *nummer)
{
	int entfernung=-1, anfangsstunde=-1;
	int eingabe_monat, eingabe_jahr , i=0, k, m; //m - fuer die neue Nummer und p fuer noch mal neue
	//char eingabe_name[10];
	//float gesamtpreis;
	struct telefonat monatsanruf[100];

	do
	{
	printf("\nVon welchem Monat(1=Jan...12=Dez) wollen Sie die Rechnung sehen?: \n");
	scanf("%d", &eingabe_monat);
	printf("\nVon welchem Jahr wollen Sie die Rechnung sehen?: \n");
	scanf("%d", &eingabe_jahr);
	puffer();
	}while((eingabe_monat < 0 || eingabe_monat > 12) || (eingabe_jahr < 1980 || eingabe_jahr > 2017));

	// if (anruf[i].datum.monat != eingabe_monat && anruf[i].datum.jahr != eingabe_jahr) 
	// 	printf("Kein WG-Mitgied hat telefoniert!\n");	
	// else
	// {
	for (i = 0; i < *nummer; i++)
	{

		if (anruf[i].datum.monat == eingabe_monat && anruf[i].datum.jahr == eingabe_jahr)
		{		/*hier werden die Gespraeche eines ausgewaehlten Monates ausgegeben*/
			 printf("           Datum           Uhrzeit           Dauer (m:s)           Zone			Betrag\n");
		if (anruf[i].name==1)
			printf("Anna\n");
		else if (anruf[i].name==2)
			printf("Franz\n");
		else if (anruf[i].name==3)
			printf("Lotta\n");
		else if (anruf[i].name==4)
			printf("Chris\n");
		else if (anruf[i].name==5)
			printf("Mark\n");
		printf("Nr.%2.0i     |" , i+1);
		printf("%2.0i/%2.0i/%2.0i     | " , anruf[i].datum.tag, anruf[i].datum.monat, anruf[i].datum.jahr);
		printf("%2.0i:%2.0i          | " , anruf[i].anfangsstunde, anruf[i].anfangsminute);
		printf("%2.0i:%2.0i             | " , anruf[i].dauer.minuten, anruf[i].dauer.sekunden);
		if (anruf[i].entfernung == 1 )
		{
			printf("Ortsgespraech");
		}
		if (anruf[i].entfernung == 2 )
		{
			printf("Ferngespraech");
		}
		if (anruf[i].entfernung == 3 )
		{
			printf("Auslandsgespraech");
		}
		// einheiten(anruf, anfangsstunde, entfernung);
		anruf[i].preis=((anruf[i].dauer.gesamt)/einheiten(anruf, anfangsstunde, entfernung, nummer))*0.06;
		printf(" 	|	%4.2f Euro\n",anruf[i].preis);
		m = 0;
		monatsanruf[m] = anruf[i];
		m++;
		
		for (k = 0; k < m; k++)
		{	
			//gesamtpreis = 0;
			monatsanruf[k].gesamtpreis += monatsanruf[k].preis;
			printf("Der Monatsbetrag betraegt: %.2f Euro\n", monatsanruf[k].gesamtpreis);
		}
		}
	// }
	}
	
	
	printf("\nDu willst zurück ins Menue? Druecke ENTER!\n");
	//puffer();
	//clear();
}


double einheiten(struct telefonat anruf[100],int anfangsstunde, int entfernung, int *nummer)
{

	float tarifliste [24][3];
	FILE *dz;

    dz = fopen("tarifliste.inp","r");
	
	int n,m,i;
	double a;

	/*Tabelle wird abgelesen*/
	for (n = 0; n < 24; n++)
	{
		for (m = 0; m < 3; m++)
		{
			fscanf(dz, "%f", &tarifliste[n][m]);
		}			
	}

	for ( i = 0; i < *nummer; ++i)
	{
		a = tarifliste[anruf[i].anfangsstunde-1][anruf[i].entfernung-1];
	}
	
	
	fclose(dz);
	return a;
}
/*hier werde alle Gespraeche eines Monats geloescht*/
void monatsloeschen(struct telefonat anruf[100], int *nummer)
{
	int i, eingabe_monat, eingabe_jahr;
	
	do
	{
		printf("Monat eingeben: \n");
		scanf("%d", &eingabe_monat);
		printf("Jahr eingeben: \n");
		scanf("%d", &eingabe_jahr);
		puffer();
	}while((eingabe_monat < 0 || eingabe_monat > 12) || (eingabe_jahr < 1980 || eingabe_jahr > 2017));
	
	for (i = 0; i < *nummer; i++)
	{
		if (anruf[i].datum.monat == eingabe_monat && anruf[i].datum.jahr == eingabe_jahr)
		{
			printf("Folgende/s Gespraech/e werden gelöscht\n");
		if (anruf[i].datum.monat == eingabe_monat && anruf[i].datum.jahr == eingabe_jahr)
		{		/*hier werden die Gespraeche eines ausgewaehlten Monates ausgegeben*/
			 printf("           Datum           Uhrzeit           Dauer (m:s)           Zone			Betrag\n");
		if (anruf[i].name==1)
			printf("Anna\n");
		else if (anruf[i].name==2)
			printf("Franz\n");
		else if (anruf[i].name==3)
			printf("Lotta\n");
		else if (anruf[i].name==4)
			printf("Chris\n");
		else if (anruf[i].name==5)
			printf("Mark\n");
		printf("Nr.%2.0i     |" , i+1);
		printf("%2.0i/%2.0i/%2.0i     | " , anruf[i].datum.tag, anruf[i].datum.monat, anruf[i].datum.jahr);
		printf("%2.0i:%2.0i          | " , anruf[i].anfangsstunde, anruf[i].anfangsminute);
		printf("%2.0i:%2.0i             | " , anruf[i].dauer.minuten, anruf[i].dauer.sekunden);
		if (anruf[i].entfernung == 1 )
		{
			printf("Ortsgespraech");
		}
		if (anruf[i].entfernung == 2 )
		{
			printf("Ferngespraech");
		}
		if (anruf[i].entfernung == 3 )
		{
			printf("Auslandsgespraech");
		}
		}
	}
		// else 
		// {
		// 	printf("Kein WG-Mitgied hat telefoniert!\n");
		// 	anruf_monat[q] = anruf[i];
		// 	q++;
		// }
	}
	nummer =  nummer - i;
	//nummer_speichern(nummer);
	printf("\n\nDu willst zurück ins Menue? Druecke ENTER!\n");
	//clear();
}




seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

gingerP schrieb:

Nun bekomme ich beim Ausführen direkt ein Segmentation Fault:11.

Da fehlen noch Informationen. Wir wissen z.B. nicht, was in den Dateien steht, die vom Programm eingelesen werden.

Könnt ihr mir sagen, woran das liegen könnte?

Warum fragst du nicht einen Debugger wie gdb?

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

Und fread() erwartet einen Pointer auf das Struct: http://www.cplusplus.com/reference/cstdio/fread/

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@seahawk1986: Das es Array ist, ist das ja auch gleichzeitig ein Zeiger‽

@gingerP: Das Stichwort ist Fehlerbehandlung. Der Code fängt gleich von Anfang an an einfach davon auszugehen das bestimmte Aufrufe fehlerfrei funktionieren und prüft nicht das Funktionsergebnis ob das tatsächlich der Fall war. Und wenn man dann ungültige Daten einfach ungeprüft in einem weiteren Funktionsaufruf verwendet, passieren komische Dinge, bis hin zum Segfault.

Du solltest dringend an der Formatierung des Quelltextes arbeiten. Das sieht sehr unübersichtlich aus. Es gibt da auch Werkzeuge um Quelltext sauber zu formatieren, aber eigentlich sollte man das schon selbst beim schreiben machen. Da geht es nicht um ”Schönheit” sondern darum das man den Code leichter lesen und verstehen kann um Fehler zu vermeiden.

Ich habe mir das jetzt nur bis zur main() durchgelesen und habe ein paar Anmerkungen:

Im struct dauer und im struct telefonat werden redundante Daten gespeichert. gesamt und gesamtpreis kann man problemlos und schnell aus den anderen Daten ausrechnen. Beziehungsweise würde ich bei der Dauer einfach nur die Gesamtsekunden speichern. Minuten und Sekunden sind ja eher für die Anzeige gedacht, und dafür kann man dann die Gesamtsekunden umrechnen. Der Grund keine redundaten Daten zu speichern ist das man dann immer und überall aufpassen muss, dass man keine Änderungen an den Daten vornimmt, die diesen Zusammenhang zwischen den Feldern verletzen. Diese Fehlerquelle kann man vermeiden.

Die Zahltypen für die Felder könnte man passender wählen. Tag und Monat verlassen beispielsweise nicht den Wertebereich eines 8-Bit-Zahltyps und können auch nicht negativ sein, das wäre also eher ein uint8_t aus inttypes.h und kein int mit Vorzeichen und von dem man nicht weiss wie viele Bits das auf der Zielplattform haben wird.

Sofern mann nicht mit gebrochenen Centbeträgen arbeiten wird, würde ich die Preise als ganze Zahlen in Cent verarbeiten. Damit umgeht man potentielle Probleme mit der Ungenauigkeit von Gleitkommazahlen.

telefonat hat ein name-Feld als int, was ungewöhnlich ist. Das würde man eher name_index oder name_id nennen.

Das entfernung eine Kennzahl für Orts oder Ferngespräch ist, sollte man vielleicht durch einen Aufzählungstyp (enum) deutlich machen, und im Code mit switch arbeiten wenn man irgendwo alle Fälle behandeln muss, denn die meisten C-Compiler können einen warnen wenn man nicht jeden Fall abdeckt. Zudem macht es sinn auch den Fall im Code abzudecken, dass dort ein Wert steht, der nicht vorgesehen ist, und solche Fehlerfälle nicht einfach unbehandelt durchgehen lassen. Mindestens beim Einlesen der Daten aus einer Datei würde ich das prüfen.

Bei den Prototypen fällt auf, das sehr oft ein Argument mit dieser unhandlichen Deklaration: struct telefonat anruf[100] beschrieben wird. Zum einen kommt die 100 viel zu oft im Quelltext als magische Zahl vor. Stell Dir mal vor es wird viel telefoniert und Du musst die Grösse anpassen, wie oft Du dann 100 im Quelltext durch eine andere Zahl ersetzen musst. Dazu musst Du dann jede 100 suchen, schauen ob sie etwas mit dieser Arraygrösse zu tun hat oder nicht, und sie dementsprechend ändern oder nicht. Das ist fehleranfällig, denn es kann sein das man vorkommen übersieht, oder Zahlen ändert die etwas anderes bedeuten, oder sich bei einer Änderung vertippt. Deswegen definiert man so etwas am Anfang als Konstante, so dass man es nur an einer Stelle für das gesamte Programm ändern kann.

Und wenn man diese Konstante hat, würde ich einfach nur einen Zeiger auf struct telefonate-Werte übergeben, also statt struct telefonat anruf[100] nur struct telefonat *anruf.

Der Name anruf ist nicht so toll. Es handelt sich ja nicht um einen Anruf sondern um 100, also sollte es mindestens anrufe heissen. Wenn der Typ aber struct telefonat lautet, warum dann überhaupt noch einen anderen, zusätzlichen Begriff verwenden und die Variable(n) nicht einfach telefonate nennen?

Nebenbemerkung: structs haben in C einen eigenen Namensraum, es ist also möglich eine Variable genau wie das struct zu nennen, also Beispielsweise ein Telefonat als struct telefonat telefonat; zu deklarieren. Andererseits ist es nicht unüblich structs gar keinen Namen zu geben sondern mit typedef einen Namen ausserhalb des struct-Namensraum zu definieren und den dann beispielsweise mit einem _t-Suffix zu versehen oder mit einem Grossbuchstaben zu versehen, damit ihn als Typ erkennt. Dann spart man sich das struct überall immer wieder zu schreiben und hat Telefonat telefonat; oder telefonat_t telefonat; als Deklaration.

Die Namen für die Dateivariablen in der main() sind schlecht. Namen die eine Tätigkeit beschreiben, verwendet man für Funktionen, nicht für Werte die ”Dinge” beschreiben. Niemand würde, ohne die Deklaration zu sehen, bei feldlesen oder feld_schreiben darauf kommen, das es sich dabei um FILE*-Werte handelt! Und es ist auch nicht nötig dafür zwei verschiedene Namen zu verwenden wenn man die nie gleichzeitig verwendet. Beide könnte man durch telefonate_file ersetzen, was die Bedeutung wesentlich besser beschreibt. Warum sind die FILE*-Namen zum *lesen ohne Unterstrich und die zum *_schreiben mit Unterstrich? Konsistenz hilft Fehler zu vermeiden.

Die Dateien die dort gespeichert und geladen werden sind Binärdaten, dementsprechend sollte man die Datei(en) auch im Binärmodus öffnen, sonst funktioniert dieses Programm nicht auf jeder Plattform.

Und wenn es funktioniert, dann kann die Daten nicht auf jedem anderen System weiterverwenden. Einfach so Arrays mit Strukturen aus dem Speicher auf die Platte schreiben und von dort wieder lesen ist nicht portabel. Nicht einmal wenn man in den Strukturen keine Typen wie int verwendet, deren Speichergrösse nicht genau festgelegt ist, denn man hat dann immer noch Probleme mit der Ausrichtung der Daten und mit der ”Endianess” bei Zahltypen die mehr als ein Byte belegen. Das funktioniert alles nur auf der Plattform für die es kompiliert wurde.

Die Anzahl der belegten Einträge würde ich nicht in einer zusätzlichen Datei speichern, sondern eine weitere Struktur anlegen wo die Anzahl und die Anrufe gespeichert werden. Die Daten braucht man dann auch nicht komplett laden und speichern, sondern kann sich auf den Teil beschränken, der tatsächlich mit Telefonaten belegt ist.

Die Vornamen Anna, Franz, … tauchen mehrfach im Programm auf. Das gleiche Problem wie mit der 100: Redundante Daten und redundanter Code sind beim schreiben und bei Änderungen fehleranfällig und bei letzterem mit Mehraufwand verbunden. Zudem ist das eigentlich eine Schleife die dort steht wenn für fünf Namen immer wieder das gleiche macht und sich dabei nur der Name und eine aufsteigende Zahl ändert. Da steckt man die Namen in ein Array. Und der gleiche Code wiederholt sich dann auch noch zwei mal → in eine Funktion heraus ziehen.

Die Namen fangen in der Nummerierung bei 1 an und nicht bei 0, das ist unpraktisch, zum Beispiel für einen Zugriff in ein Array mit Namen. Man muss dann entweder den ersten Platz mit einem Dummy-Wert belegen, oder für Indexzugriffe immer umrechnen.

nummer ist auch kein guter Name, da weiss man nur das es eine Zahl ist, aber nicht wirklich wofür die steht. name_index oder name_id wäre hier wieder passender. Am besten der gleiche Name den auch das Feld in struct telefonat hat, damit man den Zusammenhang sehen kann.

Die wirre Einrückung macht es verdammt schwer schnell zu sehen ob in dem switch alle cases mit break enden und ob das schreiben der Datei zum default im switch gehört oder ob es erst nach dem switch-Konstrukt steht.

(Puh, ist doch ganz schön lang geworden. ☺)

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

Marc_BlackJack_Rintsch schrieb:

@seahawk1986: Das es Array ist, ist das ja auch gleichzeitig ein Zeiger‽

Ups, irgendwie habe ich den Array übersehen.

Antworten |