【问题标题】:Reading from scanf results to infinite loop从 scanf 结果读取到无限循环
【发布时间】:2024-01-13 15:36:01
【问题描述】:

我正在尝试阅读有关在 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 等)时,&lt;Entry ...&gt; 总是超出该数字。在告诉我 scanf() 已弃用之前,我想知道是否有可能在不删除 scanf() 函数的情况下修复此代码。我不想使用fgets(),因为我不知道输入包含的最大字符数。

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • scanf() 没有被弃用,但一些编码人员不喜欢使用它。但是there are ways在事先不知道行长的情况下使用fgets()
  • scanf() 通常是有问题的,但我认为没有任何理由认为它是造成这里问题的原因。
  • 啊。当student list[N]; 出现在之前 N 的值已输入时,您认为student list[N]; 会做什么?
  • @JohnBollinger 哦,有问题。您可以将其发布为答案,以便我将其标记为已解决吗?非常感谢 :) 我的错
  • 未定义的行为,投票关闭为错字。

标签: c scanf stdin


【解决方案1】:

您在可变长度数组的声明中使用了未初始化的变量 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

【讨论】:

【解决方案2】:

这里...

    int N; // number of entries

    student list[N];

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

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

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

【讨论】: