У вас есть несколько проблем:
- Оператор while () l oop не заканчивается (ваш первоначальный вопрос).
- fscanf () небезопасен - лучше альтернативы.
- Вы используете fscanf () неправильно.
- Чтение строки символом за раз неэффективно.
- Повторный вызов "reallo c ()" неэффективно - есть лучшие альтернативы.
Вот пример кода.
#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=%d\n",
student->lastName, student->id, student->grade, record_counter);
}
}
// Done
printf("Done: final record count=%d\n", 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 () over fscanf (): Недостатки scanf
Обратите внимание, что все, что связано с чтением записи ученика, находится внутри отдельной функции: enter_new_student()
. Вы также заметите, что «структура управления» - «while l oop» - это OUTSIDE функции.
Есть два (связанных) условия, которые могут вызвать oop для выхода:
- Не прочитал "id"
- Конец файла
Причина вашего оригинала "пока l oop «Неудачным было то, что fscanf()
никогда не вернется ' '
... так что вы непреднамеренно закодировали« бесконечный l oop ». Вот почему:
https://linux.die.net/man/3/fscanf
Возвращаемое значение
Эти функции успешно возвращают количество элементов ввода сопоставлены и назначены, что может быть меньше предусмотренного или даже равно нулю в случае ошибки раннего сопоставления.
Значение EOF возвращается, если достигнут конец ввода перед первым успешным преобразованием или происходит сбой сопоставления. EOF также возвращается, если происходит ошибка чтения, и в этом случае устанавливается индикатор ошибки для потока (см. Ferror (3)), и устанавливается errno, указывающий ошибку.