fscanf上的奇怪崩溃

时间:2017-03-07 19:18:33

标签: c scanf

所以,这是我即将开始的非常小的代码但是因为一个未知的原因它在scanf上崩溃了。我查看了printf,这是崩溃的地方。我已经尝试了很多东西,我可以避免这个问题,但我只是想知道如果你能告诉我什么错了。

例如,这可以是datafile:

19/03/2017 Good
17/03/2017 Terrible
18/03/2017 Good

以下是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DATA_FILE "Database.txt"
#define MAX_USERS 50

typedef struct data {
    char date;
    char feeling;
} data;

int ReadData(data *p1, FILE *fp);

int main() {
    FILE *fp = fopen(DATA_FILE, "r");
    data *p1;
    p1 = (struct data*)malloc(MAX_USERS * sizeof(struct data));
    if (fp == NULL) {
        printf("Database is empty!");
        exit(1);
    }
    ReadData(p1, fp);
}

int ReadData(data *p1, FILE *fp) {
    int i = 0;
    while (!feof(fp)) {
        fscanf(fp, "%s %s", (p1 + i)->date, (p1 + i)->feeling);
        printf("%s %s", &(p1 + i)-> date, &(p1 + i)-> feeling);
        i++;
    }
    return i;
}

4 个答案:

答案 0 :(得分:2)

您在date类型中定义feelingstruct的方式不匹配:

typedef struct data
{
    char date;
    char feeling;
}data;

以及如何在scanf电话中对待他们:

fscanf(fp, "%s %s", (p1+i)->date, (p1+i)->feeling); 

请记住,%s期望其对应的参数具有类型char *,并指向char数组的第一个元素,而不是单个焦炭。您已将datefeeling声明为单char个。而且,(p1+i)->date不会评估实例中date成员的地址

为了使其按照您的意图运行,datefeeling都需要声明为char数组

typedef struct data
{
    char date[MAX_DATE_LENGTH+1];        // where MAX_DATE_LENGTH and MAX_FEELING_LENGTH
    char feeling[MAX_FEELING_LENGTH+1];  // are constant integral expressions; +1 to account
}data;                                   // for string terminator

,您需要将datefeeling定义为char的指针,并在以后为它们分配内存:

typedef struct data
{
    char *date;
    char *feeling;
}data;
...
p1[i]->date = malloc( MAX_DATE_LENGTH + 1 );
p1[i]->feeling = malloc( MAX_FEELING_LENGTH + 1 );

现在,您的scanf来电可以进行一次小调整:

fscanf(fp, "%s %s", p1[i].date, p1[i].feeling);

(p1 + i)->date有效,但我认为使用常规下标表示法更容易阅读和遵循。

答案 1 :(得分:2)

您的代码中存在多个问题:

  • 您应该将结构date的{​​{1}}和feeling成员定义为字符数组,而不是单个data类型。例如:

    char
  • 使用指针语法typedef struct data { char date[20]; char feeling[40]; } data; 的可读性远低于等效数组语法:(p1 + i) -> date

  • p1[i].date的参数不正确:您必须传递格式为fscanf的字符数组的地址。您传递了成员的而不是他们的地址,这是崩溃的一个非常可能的原因。传递单个%s成员的地址不正确,单个char无法保存字符串。使用更新的结构定义,您应该写:

    char

    fscanf(fp, "%19s %39s", p1[i].date, p1[i].feeling); 现在是一个数组,所以将它作为参数传递实际上会传递第一个元素的地址。

    指定p1[i].date的宽度告诉19在空终结符之前不要将超过fscanf()个字符存储到目标数组中。

  • 19始终是测试文件结尾的错误方法。而是检查while(!feof(fp))成功转换2个字符串:

    fscanf()
  • 您将while (fscanf(fp, "%19s %19s", p1[i].date, p1[i].feeling) == 2) { ... 说明符的单个char值的地址传递给printf。这是不正确的。使用更新的结构定义,使用:

    %s
  • 转换printf("%s %s", p1[i].date, p1[i].feeling); 条目后,您应该停止阅读该文件。

  • 您应该检查内存分配失败

  • 您应该释放内存块

  • 您应该关闭文件

  • 将日期解析为单个单词可能没问题,但感觉应该允许多个单词,如MAX_USERSVery bad。请使用格式So so

以下是更正后的版本:

%[^\n]

答案 2 :(得分:1)

数据库中的datefeeling字段是字符串。您正在以%s格式指定fscanf将其作为字符串阅读。但是您试图将它们存储在只有1个字节长度的内存位置。

替换

typedef struct data
{
    char date;
    char feeling;
}data;

typedef struct data
{
    char date[11];
    char feeling[20];
}data;

答案 3 :(得分:0)

char日期;是一个单一的char。你需要像char date这样的东西[20];使用格式规范%s。