我正在尝试将file.txt
中的信息读入BST。
首先,我考虑将信息保存到临时小型数组中,而不是将这些值分配给树节点。显然出现了问题,我确信有一件事是不正确的正则表达式,可能是别的东西。请帮我弄清楚如何将数据保存到BST,我这个项目真的很晚。
输入file.txt
中包含的数据样本:
3800 Lee, Victor; 2.8
3000 Brown, Joanne; 4.0
1300 South, Frankie; 2.6
4000 Trapp, Dave; 3.9
必须阅读并解析它们:1)int= id
,2)char= name
,3)float= gpa
他们必须妥善保存,没有任何符号,所以当我在下一个功能中搜索时,它不会给我任何错误。
以下是我的代码(更新):
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;
答案 0 :(得分:2)
这是因为fscanf
的格式字符串错误。你需要的是"%d %[^;];%f "
。
这意味着
;
以外的任何数量的所有字符并存储它。写入字符的缓冲区必须足够大,以便读取字符加上fscanf
添加的终止空字节。;
并丢弃它如您所见,如果文件中的任何行格式不正确,则fscanf
将因匹配失败而失败,并可能将文件指针留在未知位置。
您应该使用fgets
来读取一行,然后使用sscanf
来处理该行并从中读取元素。这是你应该怎么做的。但是,您必须事先知道文件中一行的最大长度。
您的代码段中还有其他错误。
您正在分配内存以存储指针,而不是由此构建结构 - stuPtr = (STUDENT*)malloc (sizeof (stuPtr));
您应该执行以下操作。另外,不要投射malloc
的结果并检查NULL
的结果 -
stuPtr = malloc(sizeof *stuPtr);
您无法分配数组。您应该复制数组的每个字符。此外,结构成员name
是一个字符,而不是一个数组。
stuPtr->name = tempName;
在上面的语句中,tempName
是一个数组,它衰变成指向其第一个元素的指针。该指针被分配给结构成员name
,这是一个字符 - 这显然是一个错误。您应该将结构成员name
的类型更改为char
数组。
这是我修改过的修改版本。
#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;
}
}
答案 1 :(得分:1)
关于阅读文件:如果未能转换所有占位符,则返回值不一定为EOF
,并且您的格式字符串与文件中的格式不对应。
fscanf
返回成功转化的次数。当输入用完时,它返回EOF
。在您的情况下,格式字符串将仅转换第一个项目,因此返回值为1.您正在寻找3.(当fscanf
未转换所有项目时,它会被卡住。当您尝试阅读时下一行,你真的试着从fscanf
放弃转换的地方读取,这通常不是你想象的那样。)
文件中条目的格式为:
3800 Lee, Victor; 2.8
您的格式字符串是:
"%4d, %[^\t\n,;]c %f"
这里有几件事。
c
无法理解c
。所以你的格式应该是这样的:
"%d %29[^;]; %f "
全力以赴:
while (fscanf (f, "%d %[^;]; %f ", &id, name, &gpa) == 3) {
printf("1 %4d %-20s%f\n", id, name, gpa);
}
这将停止在第一行无法转换,所以如果你有一个拼写错误,或许在第一行中丢失分号,则不会读取任何内容。这是不可取的。由于您的文件格式是基于行的,因此我建议先阅读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);
}
}
现在跳过坏行,并显示(简洁)错误消息。
哦,专注于真正的问题,不要过于花哨。虽然像这样塞满了所有东西:
if(!(fpStudents = fopen("gpa.txt", "r")))
printf("-*- Could not open file for reading! -*-\n"), exit(100);
可能会给你h4xx0r学分,你的代码会更好地呈现为:
fpStudents = fopen("gpa.txt", "r");
if (fpStudents == NULL) {
printf("-*- Could not open file for reading! -*-\n");
exit(100);
}
您可以在glace中看到所需的一切:打开文件。如果出现问题,请打印一条消息并退出。我很难从你的代码中读到这些而没有眯眼。条件和逗号运算符中的赋值是七十年代。
答案 2 :(得分:0)
我对你的代码的说明:
sizeof (stuPtr) should be sizeof (STUDENT).
你必须将类型定义传递给大小,分配该类型的字节数。