为什么将数据读入文本文件时fscanf出现分段错误?

时间:2019-09-24 17:25:10

标签: c struct segmentation-fault text-files

我正在尝试从其中包含一些数据的文本文件中读取数据。


我的文本文件:

1 dior Asfiya 20 abcde 12345
2 abde Sabah 17 saar 5757657

我的代码:

typedef long long int ulong;
struct Customer
{
    char name[25];
    int acc_no;
    int age;
    char gender[2];
    char address[60];
    ulong phone;
    char password[10];


};
struct Customer add,check;

int new_acc()
{
        int c;
        FILE *p;
        FILE *q;
        p = fopen("test.txt","a");
        q = fopen("test.txt","r");
        if(p == NULL)
        {
            puts("Could't open file\n");
            return(-1);
        }
        if(q == NULL)
        {
            puts("Couldn't open file\n");
            return(-1);
        }
        account_no:
        printf("\nAdd record");
        printf("\nEnter account number: ");
        scanf("%d",&check.acc_no);
        while(c = fscanf(q,"%d %s %s %d %s %s %llu%[^\n]",&add.acc_no,add.password,add.name,&add.age,add.gender,add.address,&add.phone) == 7)
        {
            if(check.acc_no==add.acc_no)
            {
                printf("\nAccount no. already in use!");
                goto account_no;
            }
        }
        if(c != EOF){
            goto details;
        }
        details:
        add.acc_no = check.acc_no;
        printf("\nEnter password: ");
        scanf("%s",add.password);
        printf("\nFull Name: ");
        scanf("%s",add.name);
        printf("\nEnter your age: ");
        scanf("%d",&add.age);
        printf("\nEnter your gender: ");
        scanf(" %c",&add.gender);
        printf("\nEnter address: ");
        scanf("%s",add.address);
        printf("\nEnter phone number: ");
        scanf("%llu",&add.phone);
        fprintf(p,"%d %s %s %d %s %s %lld\n",add.acc_no,add.password,add.name,add.age,add.gender,add.address,add.phone);
        fclose(p);
        fclose(q);

}

在调试代码时,当 while 循环启动时,它会给出分段错误。在将第一行数据添加到文件之前,它工作得很好。我不知道为什么会这样。

2 个答案:

答案 0 :(得分:2)

在编写时,您没有正确设置c

while(c = fscanf(q,"%d %s %s %d %s %s %llu%[^\n]",&add.acc_no,add.password,add.name,&add.age,add.gender,add.address,&add.phone) == 7)

这是将c设置为==比较的结果,因为==的优先级高于=

此外,您不需要在格式字符串的末尾使用[^\n]。开头的%d将跳过任何空格,包括上一行末尾的换行符。

应该是:

while((c = fscanf(q,"%d %s %s %d %s %s %llu",&add.acc_no,add.password,add.name,&add.age,add.gender,add.address,&add.phone)) == 7)

我不确定您打算做什么

        if(c != EOF){
            goto details;
        }
        details:

由于details:紧接在if语句之后,因此无论条件是否成功,您都去那里。

您应该摆脱使用goto的习惯,这通常被认为是较差的编程风格。将条件为真时应运行的代码放入if中。您可以使用continuebreak重新启动并结束循环。

答案 1 :(得分:2)

Remove goto

请重构代码的这一部分。


关于等待存储字符串的数组-您是否考虑了字符串NULL终止符,还需要存储数组的单元格吗?

无论如何,我看到gender的大小为2,但是您的输入表明它需要更多。

您的输入有7个令牌:

  

1 dior Asfiya 20 abcde 12345

这意味着gender溢出,调用未定义行为(UB),因为您将尝试将长度为4个字符的字符串存储到大小为2的数组中。这可能解释了崩溃。

通过检查7个值,您会看到它,但是您的代码中还有另一个问题,您可以在下一节中阅读。

您可能是说:

  

1 dior Asfiya 20 abcde f 12345


更改此:

while(c = fscanf(q,"%d %s %s %d %s %s %llu%[^\n]",&add.acc_no,add.password,add.name,&add.age,add.gender,add.address,&add.phone) == 7)

对此:

while((c = fscanf(q,"%d %s %s %d %s %s %llu%[^\n]",&add.acc_no,add.password,add.name,&add.age,add.gender,add.address,&add.phone)) == 7)

因为operators priority,比较发生在赋值之前,这不是您想要的。您要先分配给变量,然后再进行比较,所以请使用括号指定所需的优先级。