我有一个关于动态分配和结构的问题。 任务:我有一个学生结构,看起来像这样:
typedef struct{
unsigned id;
char *lastName;
float grade;
}students_t;
我不允许向 lastName 传递最大数量的字符,它必须保持一个指针,我每次都会增加大小。
我的代码如下所示:
unsigned counter = 0;
students_t* students = NULL;
students_t temp;
char char_current;
unsigned char_counter=0;
while (fscanf(inputFile,"%u",&temp.id) == 1) {
students = realloc(students,(counter+1) * sizeof(students_t));
students[counter].id=temp.id;
printf("%d",students[counter].id);
students[counter].lastName = NULL;
while (fscanf(inputFile,"%c",&char_current) != ' ') {
students[counter].lastName = realloc(students[counter].lastName,(char_counter+1) * sizeof(char));
students[counter].lastName[char_counter] = char_current;
char_counter++;
}
students[counter].lastName[char_counter] = ' ';
fscanf(inputFile,"%f",&students[counter].grade);
counter++;
}
我的问题出在while
的fscanf
(因为程序进入无限循环(,但我不知道如何实际解决它。
如果有人能帮助我弄清楚,我将不胜感激。 谢谢!
您有几个问题:
- while(( 循环没有终止(您的初始问题(。
- fscanf(( 是不安全的 - 有更好的选择。
- 您错误地使用了 fscanf((。 一次
- 读取一个字符串是低效的。
- 反复调用"realloc(("是低效的 - 有更好的选择。
下面是一些示例代码。
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define MAX_STRING 80
typedef struct {
unsigned id;
char *lastName;
float grade;
} students_t;
students_t* enter_new_student (FILE *inputFile)
{
char buffer[MAX_STRING];
unsigned id;
int iret;
// Check for end of input
iret = fscanf(inputFile, "%u", &id);
if ((iret < 1) || feof(inputFile)) { // iret should be "1" if successful
return NULL;
}
// Allocate a record and read its data
students_t *student = (students_t *)malloc(sizeof(students_t));
iret = fscanf(inputFile, "%s %f", buffer, &student->grade); // iret should be "2" if successful
student->id = id;
student->lastName = strdup(buffer); // strdup() does an implicit "malloc()" and "strcpy()"
// Return new student
return student;
}
int main()
{
students_t *student = NULL;
int record_counter = 0;
FILE *fp;
// Open file
if (!(fp = fopen("tmp.txt", "r"))) {
perror("unable to open file");
return 1;
}
// Read student records
while ((student = enter_new_student(fp))) {
if (student) {
++record_counter;
printf("new student=%s,id=%u, grade=%f, record_counter=%dn",
student->lastName, student->id, student->grade, record_counter);
}
}
// Done
printf("Done: final record count=%dn", record_counter);
return 0;
}
下面是一个示例"tmp.txt"文件:
1 Johnson 4.0
2 Jackson 3.5
3 Jamison 3.85
以及相应的样本输出:
new student=Johnson,id=1, grade=4.000000, record_counter=1
new student=Jackson,id=2, grade=3.500000, record_counter=2
new student=Jamison,id=3, grade=3.850000, record_counter=3
一般来说,更喜欢使用 fgets(( 而不是 fscanf((: scanf 的缺点
请注意,我将与读取学生记录有关的所有内容都放在一个单独的函数中:enter_new_student()
。 您还会注意到"控制结构" - "while 循环"在函数之外。
有两种(相关(条件可能导致循环退出:
- 没有读"id">
- 文件结尾
您最初的"while循环"失败的原因是fscanf()
永远不会返回' '
......所以你无意中编码了一个"无限循环"。 原因如下:
https://linux.die.net/man/3/fscanf
返回值
这些函数返回成功匹配和分配的输入项数,该数可以少于提供的输入项数 for,在早期匹配失败的情况下甚至为零。
如果在以下任一之前到达输入结束,则返回值 EOF 发生第一次成功转换或匹配失败。EOF是 如果发生读取错误,也返回,在这种情况下,错误 设置了流的指示符(参见 ferror(3((,并设置了 errno 指示错误。