从 scanf 结果读取到无限循环

Reading from scanf results to infinite loop

我正在尝试在 for 循环中使用 scanf() 读取有关学生的信息(N 次 -> N 由用户输入),但是 for() 循环不止于此......它根本不会停止。我已经尝试了字符串格式的所有组合,但似乎没有任何效果。

这是我的代码:

#include <stdio.h>
#include <string.h>

typedef struct STUDENT_CONSTRUCTOR {
    char first_name[35], last_name[35];
    char gender;
    int grade;
} student;

int main(void) {
    int N; // number of entries

    student list[N];

    printf("Number of entries: "); scanf("%d", &N);

    for (int i = 0; i<N; i++) {
        printf("<Entry %d>\n", i);
        scanf("%d %c %s %s\n", &list[i].grade, &list[i].gender, list[i].first_name, list[i].last_name);
    }
    return 0;
}

我要输入的是如下序列: 10 M Mateas Mario,其中“10”是平均成绩,“M”是性别,“Mario”是我的名字,“Mateas”是我的姓氏。

N被正确读取,list[]数组中的数据也被正确读取。 list[] 基于包含所有这些数据类型的结构。

仍然,每当我为 N 输入特定值(例如 3、4、5 等)时,<Entry ...> 总是超出该数字。在告诉我 scanf() 已被弃用之前,我想知道是否有可能在不删除 scanf() 函数的情况下修复此代码。我不想使用 fgets() 因为我不知道输入包含的最大字符数。

如有任何帮助,我们将不胜感激。谢谢。

您在可变长度数组的声明中使用了未初始化的变量 N

int N; // number of entries

student list[N];

所以程序有未定义的行为。

你需要写成

int N; // number of entries

printf("Number of entries: "); scanf("%d", &N);

student list[N];

同样在 scanf 的调用中,从格式字符串

中删除换行符 '\n'
scanf("%d %c %s %s", &list[i].grade, &list[i].gender, list[i].first_name, list[i].last_name);

您可以使用函数 scanf_s.

而不是函数 scanf

这里...

    int N; // number of entries

    student list[N];

...您正在使用 N 的不确定初始值来指定 list 的维度。未定义的行为结果。该 UB 并不局限于表现为立即失败或嘈杂失败。在这种特殊情况下,它表现为您的迭代没有在您期望的地方停止。

虽然对 UB 特定表现的 机制 的推理通常不是很有效,但它似乎通常会激发某种反常的好奇心,所以我会推测在你的情况下,list 被赋予的元素比你最终请求的要少,甚至可能是 0,结果,你的输入超出了它的界限,导致 N 的值意外改变。

通过在 list 的声明 N 之前输入 N 来修复它,或者只用固定数量的元素声明 list足够大以容纳每个可接受的值 N.