所以,这是我即将开始的非常小的代码但是因为一个未知的原因它在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;
}
答案 0 :(得分:2)
您在date
类型中定义feeling
和struct
的方式不匹配:
typedef struct data
{
char date;
char feeling;
}data;
以及如何在scanf
电话中对待他们:
fscanf(fp, "%s %s", (p1+i)->date, (p1+i)->feeling);
请记住,%s
期望其对应的参数具有类型char *
,并指向char
的数组的第一个元素,而不是单个焦炭。您已将date
和feeling
声明为单char
个。而且,(p1+i)->date
不会评估实例中date
成员的地址。
为了使其按照您的意图运行,date
和feeling
都需要声明为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
或,您需要将date
和feeling
定义为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_USERS
和Very bad
。请使用格式So so
。
以下是更正后的版本:
%[^\n]
答案 2 :(得分:1)
数据库中的date
和feeling
字段是字符串。您正在以%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。