从 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
.
我正在尝试在 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
.