如标题所示。 简单的练习,尝试学习结构和其他必要的c功能。 这是一个包含char []和数字的结构,我尝试将其值保存在文件中并将其读回。 我通过fopen()阅读了很多关于Seg.fault的主题,但找不到我的错误! 有人知道为什么fopen()会在这个例子中崩溃吗? 欢迎任何有关此事的建议和批评!
Segfault发生的功能是load()
:
void load(struct Telephon *structure, int *counter)
{
char filename[255];
char puffer[255], puffercpy[255];
int i, c, newline_count;
size_t strlaen;
FILE *datei=NULL;
char *token=NULL;
printf("\033[0;35mWelche Datei oeffnen?\033[0m\n");
scanf("%s", filename);
//emptystdin();
//strlaen=strlen(filename);
//printf("%d", strlaen);
//filename[strlaen+1] = '\0';
//printf("\n%s", filename);
datei = fopen(filename, "r");
if(datei==NULL)
{
printf("\033[0;31mKonnte Datei %s nicht oeffnen.\033[0m\n", filename);
}
else
{
while ( (c=fgetc(datei)) != EOF ) //count lines of file
{
if ( c == '\n' )
{
newline_count++;
}
}
for(i=0; i<=newline_count; i++) //get values in between ";"
{
fgets(puffer, 254, datei);
strcpy(puffercpy, puffer);
token = strtok(puffercpy, ";");
*counter = atoi(token);
token = strtok(NULL, ";");
strcpy(structure[i].name, token);
token = strtok(NULL, ";");
structure[i].nummer = atoi(token);
}
fclose(datei);
}
return;
}
整个代码,主要在最后:
telephonListen.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#define MAX 100
struct Telephon
{
char name[210];
unsigned int nummer;
}TELE[MAX];
char* gotTime(char *timestrg)
{
time_t now;
now = time(NULL);
strftime (timestrg, 19, "%d.%m.%Y, %H:%M", localtime (&now));
return timestrg;
}
void printT(struct Telephon *structarray, int addcount)
{ int i;
if(addcount==0)
{
printf("\033[0;31mEs sind noch keine Eintraege vorhanden!\033[0m\n");
return;
}
else
{
for(i=0; i<addcount; i++)
{
printf("\nEintrag Nr.%d\n%s:\t%d\n",i+1, structarray[i].name, structarray[i].nummer);
}
return;
}
}
void eingabe(int num, struct Telephon *structarray)
{
size_t inputlen;
int check;
if(num>MAX)
{
printf("\033[0;31mMaximale Anzahl von Eintraegen erreicht!\033[0m\n");
return;
}
else
{
printf("\n\033[0;35mNamen eingeben:\t\033[0m");
//fgets(structarray[num].name, MAX, stdin);
fgets(structarray[num].name, 209, stdin);
inputlen=strlen(structarray[num].name);
structarray[num].name[inputlen-1]='\0';
printf("\n\033[0;35mNummer eingeben:\t \033[0m");
do
{
check = scanf("%10u", &structarray[num].nummer);
}while( getchar()!='\n');
fflush(stdin);
if(check==1)
{
printf("Ihr Kontakt wurde angelegt!\n%s:\t%u\n", structarray[num].name ,structarray[num].nummer);
}
else
{
printf("Fehler bei der Eingabe. Kontakt wurde nicht angelegt!");
return;
}
return;
}
}
void writeFile(struct Telephon *structure, char *zeitf, int counter)
{
char filename[255];
int i;
FILE *datei;
if(counter>0)
{
printf("\033[0;35mIn welche Datei soll das Telephonbuch geschrieben werden?\n(Achtung: Vorhandene Dateien werden ueberschrieben!)\t\033[0m\n");
scanf("%s", filename);
getchar();
datei = fopen(filename, "w");
if(NULL == datei)
{
printf("\033[0;31mKonnte Datei %s nicht öffnen.\033[0m\n", filename);
}
fprintf(datei, "Telephonverzeichnis vom %s\nNAME\t\t|NUMMER\n\n", zeitf);
for(i=0; i<counter; i++)
{
fprintf(datei, "%s\t\t|%d\n", structure[i].name, structure[i].nummer);
}
printf("\033[0;32mDatei gespeichert.\033[0m\n");
fclose(datei);
}
else
{
printf("\033[0;31mEs sind noch keine Eintraege vorhanden!\033[0m\n");
return;
}
return;
}
void change(struct Telephon *structure, int count)
{
int eintragnum;
if (count == 0)
{
printf("\033[0;31mEs sind noch keine Eintraege vorhanden!\033[0m\n");
return;
}
else
{
printT(structure, count);
printf("\033[0;31mWelcher Eintrag soll geaendert werden?\033[0m\n");
do
{
scanf("%d", &eintragnum);
}while(getchar()!='\n');
if(eintragnum<1||eintragnum>count)
{
printf("\033[0;31mBitte die Nummer [zwischen %d und %d]\n des zu aendernden Eintrags eingeben!\033[0m\n", 1, count);
}
else
{
eingabe(eintragnum-1, structure);
}
}
return;
}
void emptystdin()
{
int c;
while( ((c = getchar()) != EOF) && (c != '\n') );
}
void searchContact(struct Telephon *structure, int count)
{
char searchC;
int inputlen;
int i=0;
int countcompare;
if (count == 0)
{
printf("\033[0;31mEs sind noch keine Eintraege vorhanden!\033[0m\n");
return;
}
else
{
printf("Anfangsbuchstabe:\t");
scanf("%c", &searchC);
emptystdin();
for(i=0; i<count; i++)
{
if(structure[i].name[0]==searchC)
{
printf("Eintrag gefunden:\n");
printf("Nr. %d\nName:\t%s\nNummer:\t%u\n", i+1, structure[i].name, structure[i].nummer);
}
}
return;
}
}
void save(struct Telephon *structure, int counter)
{
char filename[255];
int i;
FILE *datei;
if(counter>0)
{
printf("\033[0;35mUnter welchem Dateinamen speichern?\n(Achtung: Vorhandene Dateien werden ueberschrieben!)\t\033[0m\n");
scanf("%s", filename);
emptystdin();
datei = fopen(filename, "w");
if(NULL == datei)
{
printf("\033[0;31mKonnte Datei %s nicht anlegen.\033[0m\n", filename);
}
for(i=0; i<counter; i++)
{
fprintf(datei, "%d;%s;%d\n", i+1, structure[i].name, structure[i].nummer);
}
printf("\033[0;32mDatei gespeichert.\033[0m\n");
fclose(datei);
}
else
{
printf("\033[0;31mEs sind noch keine Eintraege vorhanden!\033[0m\n");
}
return;
}
void load(struct Telephon *structure, int *counter)
{
char filename[255];
char puffer[255], puffercpy[255];
int i, c, newline_count;
size_t strlaen;
FILE *datei=NULL;
char *token=NULL;
printf("\033[0;35mWelche Datei oeffnen?\033[0m\n");
scanf("%s", filename);
//emptystdin();
//strlaen=strlen(filename);
//printf("%d", strlaen);
//filename[strlaen+1] = '\0';
//printf("\n%s", filename);
datei = fopen(filename, "r");
if(datei==NULL)
{
printf("\033[0;31mKonnte Datei %s nicht oeffnen.\033[0m\n", filename);
}
else
{
while ( (c=fgetc(datei)) != EOF ) //Zeilen in Datei zählen
{
if ( c == '\n' )
{
newline_count++;
}
}
for(i=0; i<=newline_count; i++) //CVS parsen/auslesen
{
fgets(puffer, 254, datei);
strcpy(puffercpy, puffer);
token = strtok(puffercpy, ";");
*counter = atoi(token);
token = strtok(NULL, ";");
strcpy(structure[i].name, token);
token = strtok(NULL, ";");
structure[i].nummer = atoi(token);
}
fclose(datei);
}
return;
}
int main(void)
{
int auswahl;
int count = 0;
char zeit[20];
char buffer[2];
struct Telephon *structptr; //malloc(MAX*(sizeof(TELE)));
structptr = TELE;
gotTime(zeit);
system("clear");
printf("Telephonkontaktverwaltung\t%s\n", zeit);
do
{
printf("\033[30;47m1: Kontakt hinzufuegen\t2: Kontakte anzeigen\n3: Kontakt aendern\t4: Als Datei speichern\n5. Kontakt suchen\n6. Als CVS sichern\t7. Aus CVS laden\n8. Beenden\nEine der Ziffern eingeben, mit Enter bestaetigen\033[0m\n");
/*
scanf("%d", &auswahl);
scanf("%c", &buffer);
fgets(buffer, 2, stdin);
if(isdigit(buffer[1]))
{
auswahl=atoi(buffer);
}
else
{
printf("Eine der Nummern eingeben um Aktion auszufuehren!\n");
}
do
{
scanf("%d", &auswahl);
}while(getchar()!='\n');
fgets(buffer, 2, stdin);
sscanf(buffer, "%d", &auswahl);
*/
scanf("%d", &auswahl);
emptystdin();
switch (auswahl)
{
case 1 : eingabe(count++, structptr);
break;
case 2 : printT(structptr, count);
break;
case 3 : change(structptr, count);
break;
case 4 : writeFile(structptr, gotTime(zeit), count);
break;
case 5 : searchContact(structptr, count);
break;
case 6 : save(structptr, count);
break;
case 7 : load(structptr, &count);
break;
case 8 : printf("ENDE\n");
break;
default : printf("Eine der Nummern eingeben um Aktion auszufuehren!\n");
break;
}
}while(auswahl!=8);
return EXIT_SUCCESS;
}
答案 0 :(得分:1)
使用rewind()
。
在while()
和for()
循环之间,文件需要从头开始。
while ( (c=fgetc(datei)) != EOF ) //count lines of file
{ ...}
rewind(datei);
for(i=0; i<=newline_count; i++) //get values in between ";"
{ ...}
强烈建议避免使用scanf()
和fgets(,,stdin)
。推荐一个。优先fgets()
。
您可能希望scanf(" %c",
代替scanf("%c",
。 (添加空间)。
次要主意:
并不是说英语是最终所有语言,但OP可能会考虑像
// Bold Red "Could not create file" EOL
const char *Err_FileCreation_format = "\033[0;31mKonnte Datei %s nicht anlegen.\033[0m\n"
printf(Err_FileCreation_format, filename);
// or
#define Err_FileCreation_fmt1 "\033[0;31mKonnte Datei "
#define Err_FileCreation_fmt2 " nicht anlegen.\033[0m\n"
printf(Err_FileCreation_fmt1 "%s" Err_FileCreation_fmt2, filename);
答案 1 :(得分:0)
假设在调用fopen()
之前未调用未定义的行为,使其崩溃的唯一方法是将非初始化或非0
终止的字符数组作为文件传递给它名称或模式。
为了避免这种情况,请通过声明它来正确初始化用于保存文件名和/或模式的所有变量:
char filename[256] = "";
为避免scanf()
允许filename
多读scanf("%255s", filename);
,请执行以下操作:
while ( (c=fgetc(datei)) != EOF ) //count lines of file
{
if ( c == '\n' )
{
newline_count++;
}
}
<强>更新强>:
此代码
for(i=0; i<=newline_count; i++) //get values in between ";"
{
fgets(puffer, 254, datei);
strcpy(puffercpy, puffer);
token = strtok(puffercpy, ";");
*counter = atoi(token);
token = strtok(NULL, ";");
strcpy(structure[i].name, token);
token = strtok(NULL, ";");
structure[i].nummer = atoi(token);
}
读取直到文件结束。
所以这段代码
fgets()
将无法读取任何内容,因为已经达到了eof。
但是代码不会测试atoi()
是否可能失败,但很高兴开始解析它未读取的内容,并且......在NULL
指向{{1}}的令牌时崩溃。