[英]Why doesn't my fscanf read?
I'm trying to read information from the file.txt
into BST. 我正在尝试将
file.txt
信息读入BST。 First, I was thinking of saving info into temporary mini-arrays, and than assigning those values to the tree nodes. 首先,我正在考虑将信息保存到临时迷你数组中,而不是将这些值分配给树节点。 Apparently something goes wrong, I'm sure that one thing is the incorrect regular expression and might be something else.
显然出了点问题,我确定一件事是不正确的正则表达式,并且可能还有其他问题。 Please help me to figure out how to save data to the BST, I'm really late with this project.
请帮我弄清楚如何将数据保存到BST,这个项目真的很晚。
Samples of data contained in the input file.txt
: 输入
file.txt
包含的数据样本:
3800 Lee, Victor; 2.8
3000 Brown, Joanne; 4.0
1300 South, Frankie; 2.6
4000 Trapp, Dave; 3.9
They have to be read and parsed into: 1) int= id
, 2) char= name
, 3) float= gpa
必须将它们读取并解析为:1)
int= id
,2) char= name
,3) float= gpa
They have to be saved properly, without any symbols, so when I will do search in my next functions it wont give me any errors. 它们必须正确保存,没有任何符号,因此当我在下一个函数中进行搜索时,不会出现任何错误。
Here is my code below(UPDATED): 这是我的下面的代码(更新):
int readFile(BST_TREE *list) {
int id = 0;
int val = 0;
int ln = 0;
float gpa = 0.0;
char name[MAX_NAME_LEN];
STUDENT *stuptr = 0;
char line[MAX_LEN];
stuptr = (STUDENT*)malloc(sizeof(STUDENT));
FILE *fp = fopen("gpa.txt", "r");
if(fp == NULL) {
printf("Error in opening file\n");
return 1;
}
while (fgets(line, sizeof(line), fp)) {
ln++;
if (sscanf(line, "%d %[^;]; %f ", &id, name, &gpa) < 3) {
printf("Syntax error in line %d.\n", ln);
} else {
printf("1 %4d %-29s%f\n", id, name, gpa);
}
}
stuptr->id = id;
strcpy(stuptr->name, name);
(stuptr->gpa) = gpa;
return 0;
}
// Typedef
typedef struct
{
int id;
char name[MAX_NAME_LEN];
float gpa;
} STUDENT;
That is because the format string of fscanf
is wrong. 这是因为
fscanf
的格式字符串错误。 What you need is "%d %[^;];%f "
. 您需要的是
"%d %[^;];%f "
。 This means 这意味着
;
;
and store it. fscanf
. fscanf
添加的终止空字节。 ;
;
and discard it As you see, if any line in the file is ill-formatted, then fscanf
will fail due to matching failure and might leave the file pointer in an unknown location. 如您所见,如果文件中的任何行格式错误,则
fscanf
将由于匹配失败而失败,并且可能会将文件指针保留在未知位置。
You should use fgets
instead to read a line and then use sscanf
to process the line and read elements from it. 您应该改用
fgets
读取一行,然后使用sscanf
处理该行并从中读取元素。 Here's how you should do it. 这是您应该如何做。 However, you must know beforehand, the maximum length a line in the file can have.
但是,您必须事先知道文件中一行的最大长度。
There are other mistakes in your code snippet. 您的代码段中还有其他错误。
You are allocating memory to store a pointer, not the structure itself by this- 您正在为此分配内存来存储指针,而不是结构本身—
stuPtr = (STUDENT*)malloc (sizeof (stuPtr));
You should do the following. 您应该执行以下操作。 Also don't cast the result of
malloc
and check its result for NULL
- 也不要
malloc
的结果并检查其结果是否为NULL
stuPtr = malloc(sizeof *stuPtr);
You cannot assign arrays. 您不能分配数组。 You should copy each character of the array instead.
您应该改为复制数组的每个字符。 Also, the structure member
name
is a character, not an array. 此外,结构成员
name
是字符,而不是数组。
stuPtr->name = tempName;
In the above statement, tempName
is an array which decays into a pointer to its first element. 在上面的语句中,
tempName
是一个数组,该数组会衰减为指向其第一个元素的指针。 This pointer is assigned to structure member name
which is a character - this is clearly an error. 该指针分配给结构成员
name
,该name
是一个字符-显然这是一个错误。 You should change the type of structure member name
into a char
array. 您应该将结构成员
name
的类型更改为char
数组。
Here's a modified version with the changes I suggested. 这是我建议的修改后的版本。
#define MAX_LEN 100
#define MAX_NAME_LEN 40
typedef struct {
int id;
char name[MAX_NAME_LEN];
float gpa;
} student;
void add_student(BST_TREE *list) {
int id, val;
float gpa;
char name[MAX_NAME_LEN]
student *stuptr;
char line[MAX_LEN];
FILE *fp = fopen("gpa.txt", "r")
if(fp == NULL) {
printf("error in opening file\n");
return 1;
}
while(fgets(line, sizeof line, fp) != NULL)
stuptr = malloc(sizeof *stuptr);
if(stuptr == NULL) {
printf("not enough memory to allocate\n");
return 1;
}
val = sscanf(line, "%d %[^;];%f", id, name, gpa)
if(val != 3) {
printf("input format error\n");
// handle it
}
stuptr->id = id;
strcpy(stuptr->name, name);
stuptr->gpa = gpa;
}
}
About reading your file: The return value is not necessarily EOF
on failure to convert all placeholders and your format string does not correspond to the format in your file. 关于读取文件:如果未能转换所有占位符,则返回值不一定是
EOF
,并且格式字符串与文件中的格式不对应。
fscanf
returns the number of successful conversions. fscanf
返回成功的转换次数。 When the input has run out, it returns EOF
. 输入用完后,将返回
EOF
。 In your case, the format string will convert only the first item, so the return value is 1. You are looking for 3. (When fscanf
does not convert all items, it is stuck. When you try to read the next line, you really try to read from where fscanf
gave up converting, which is usually not where you think it is.) 在您的情况下,格式字符串将仅转换第一项,因此返回值为1。您正在寻找3。(当
fscanf
不能转换所有项时,它会卡住。当尝试读取下一行时,您会发现确实尝试从fscanf
放弃转换的地方开始阅读,通常这并不是您认为的那样。)
The format of the entries in file is: 文件中条目的格式为:
3800 Lee, Victor; 2.8
Your format string is: 您的格式字符串是:
"%4d, %[^\t\n,;]c %f"
Several things here. 这里有几件事。
c
after the brackets cannot be understood c
无法理解 c
is. c
应该是一个分号。 So your format should look like: 因此,您的格式应如下所示:
"%d %29[^;]; %f "
Putting it all togehter: 全部放在一起:
while (fscanf (f, "%d %[^;]; %f ", &id, name, &gpa) == 3) {
printf("1 %4d %-20s%f\n", id, name, gpa);
}
This will stop on the first line that can't be converted, so if you have a typo, a missing semicolon perhaps, in the first line, nothing will be read. 这将在无法转换的第一行上停止,因此,如果您有错字,可能缺少第一行中的分号,则不会读取任何内容。 That is not desirable.
那是不可取的。 Because the format of your file is line-based, I recommend to read lines with
fgets
first, then parse the line with sscanf
: 因为文件的格式是基于行的,所以我建议先读取带有
fgets
的行,然后使用sscanf
解析该行:
char buffer[80];
int ln = 0;
while (fgets(buffer, sizeof(buffer), f)) {
int id;
float gpa;
char name[30];
ln++;
if (sscanf(buffer, "%d %[^;]; %f ", &id, name, &gpa) < 3) {
printf("Syntax error in line %d.\n", ln);
} else {
printf("1 %4d %-20s%f\n", id, name, gpa);
}
}
Now bad lines are just skipped, with a (terse) error message. 现在,仅会跳过错误行,并显示(简短)错误消息。
Oh, and concentrate on the real problem and don't get too fancy. 哦,专注于真正的问题,不要太花哨。 While cramming everything together like this:
像这样将所有东西挤在一起:
if(!(fpStudents = fopen("gpa.txt", "r")))
printf("-*- Could not open file for reading! -*-\n"), exit(100);
might give you h4xx0r credits, your code is rendered better as: 可能会给您h4xx0r积分,您的代码会更好地呈现为:
fpStudents = fopen("gpa.txt", "r");
if (fpStudents == NULL) {
printf("-*- Could not open file for reading! -*-\n");
exit(100);
}
You can see everything you need at a glace: Open a file. 您可以一目了然地看到所需的一切:打开文件。 If that goes wrong, print a message and exit.
如果那不对,请打印一条消息并退出。 I have a hard time to read that from your code without squinting.
我很难不斜视地从您的代码中读取它。 Assignments in conditionals and comma operators are so seventies .
有条件的运算符和逗号运算符的赋值是如此七十 。
My notes on your code: 我的代码注释:
sizeof (stuPtr) should be sizeof (STUDENT).
You have to pass the type definination to size of, the allocate the number of bytes of that type. 您必须将类型定义传递给size,分配该类型的字节数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.