我创建了一个小型测试程序,因为在我的大型程序中也发生了同样的问题。我是c的新手,所以也许我缺少一些明显的东西。我的程序要求用户输入学生数量和他们想要添加的课程数量。然后,我创建一个 2D 数组,其大小设置为学生数量乘以课程数量。当我测试仅进入 4 名学生和 4 门课程的程序时,此 2D 数组会导致分割错误,这意味着应该只有 16 个元素。我不确定为什么这会导致 seg 错误。
int registry[][]
是有问题的数组
我已经在有和没有 2d 数组的情况下测试了该程序,没有它它就可以正常工作。
int main (void) {
int numOfStds;
int numOfCrs;
int stdNum;
printf("How many students would you like to register:");
scanf("%d", &numOfStds );
printf("How many courses are in the program?:");
scanf("%d", &numOfCrs);
int students[numOfStds];
char courses[numOfCrs][8];
for(int i; i < numOfStds; i++){
printf("Please enter student %d's number:", i);
scanf("%d", &stdNum);
students[i] = stdNum;
}
for(int i; i < numOfCrs; i++){
printf("Please enter course %d's code (must be 7 characters long):", i);
scanf("%s", courses[i]);
}
int registry[numOfStds][numOfCrs];
for(int i; i< numOfCrs; i++){
printf("%sn", courses[i]);
}
for(int i; i < numOfStds; i++){
printf("%dn", students[i]);
}
}
在所有for
循环中,您使用的是未初始化i
索引变量。这可能会导致未定义的行为。由于行为未定义,因此registry
数组的存在与否可能会改变行为。
您应该像这样初始化每个for
循环中的i
:
for(int i = 0; i < numOfStds; i++){
我还要回应大卫的回答中提出的关切。如果调用返回状态的函数,则应始终检查状态以确保它是预期的。最好在错误发生后立即处理。编写的代码假定输入中没有错误,这在一般情况下无效。这不是一个理论问题。实际应用程序总是有可能遇到无效或格式错误的输入。
正如我在评论中指出的,您有两个主要问题。scanf ("%d/n", ...)
格式字符串是错误的,除非用户在每次输入和秒后实际输入"/n"
,否则循环变量在每个for
循环中都是未初始化的。
但更令人不安的是,您无法验证每次调用时scanf
的返回,因此单个错误键入的字符可能会导致整数转换静默失败,并且您继续前进,就好像没有任何问题一样。例如,如果用户不小心命中'e'
3
,则会发生匹配失败,从stdin
中提取字符时停止,如果您正在循环收集整数输入,则刚刚进入无限循环。
始终验证每个输入
只需要简单的验证就可以将自己从自己身上拯救出来。要验证您的输入,您可以执行以下操作:
printf("How many students would you like to register: ");
if (scanf ("%d", &numOfStds) != 1) {
fputs ("error: invalid integer input - numOfStds.n", stderr);
return 1;
}
再举一个例子:
for(int i = 0; i < numOfStds; i++){
printf ("Please enter student %d's number: ", i+1);
if (scanf("%d", &stdNum) != 1) {
fputs ("error: invalid integer input - stdNum.n", stderr);
return 1;
}
students[i] = stdNum;
}
将其放在一个完整的示例中,然后输出您可以执行的收集值:
#include <stdio.h>
int main (void) {
int numOfStds;
int numOfCrs;
int stdNum;
printf("How many students would you like to register: ");
if (scanf ("%d", &numOfStds) != 1) {
fputs ("error: invalid integer input - numOfStds.n", stderr);
return 1;
}
printf("How many courses are in the program?: ");
if (scanf ("%d", &numOfCrs) != 1) {
fputs ("error: invalid integer input - numOfCrs.n", stderr);
return 1;
}
int students[numOfStds];
char courses[numOfCrs][8];
for(int i = 0; i < numOfStds; i++){
printf ("Please enter student %d's number: ", i+1);
if (scanf("%d", &stdNum) != 1) {
fputs ("error: invalid integer input - stdNum.n", stderr);
return 1;
}
students[i] = stdNum;
}
for(int i = 0; i < numOfCrs; i++){
printf("Please enter course %d's code (must be 7 characters long): ",
i+1);
if (scanf ("%7s", courses[i]) != 1) {
fputs ("error: invalid integer input - numOfCrs.n", stderr);
return 1;
}
}
/* example output */
// int registry[numOfStds][numOfCrs];
puts ("nStudents:");
for (int i = 0; i < numOfStds; i++)
printf ("student: %dn", students[i]);
puts ("nCourses:");
for (int i = 0; i < numOfCrs; i++)
printf ("course: %sn", courses[i]);
}
(注意:在用if (scanf ("%7s", courses[i]) != 1)
保护数组边界之上,如果您未能将7
作为字段宽度修饰符包含在内,则用户可以根据需要输入任意数量的字符,从而导致未定义行为(
示例使用/输出
$ ./bin/numofstds
How many students would you like to register: 3
How many courses are in the program?: 2
Please enter student 1's number: 301
Please enter student 2's number: 302
Please enter student 3's number: 303
Please enter course 1's code (must be 7 characters long): abcdefg
Please enter course 2's code (must be 7 characters long): bcdefgh
Students:
student: 301
student: 302
student: 303
Courses:
course: abcdefg
course: bcdefgh
仔细查看,如果您有其他问题,请告诉我。