fopen导致段错误

时间:2013-10-14 14:30:10

标签: c segmentation-fault fopen file-pointer

如标题所示。 简单的练习,尝试学习结构和其他必要的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;
}

2 个答案:

答案 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}}的令牌时崩溃。