执行exe后,出现以下错误:
注意:我对编码不好而且还很陌生,所以请不要介意我的编码不好^^
注意2:我只是在弄乱随机函数。
#include <stdio.h>
#include <stdlib.h>
struct student {
char firstName[20];
char AverageNum[2];
};
void StudentScan(int, struct student[]);
void StudentPrint(int, struct student[]);
int main() {
int i;
int length;
struct student *studentp;
printf ("\nEnter the host of students: ");
scanf ("%d ", &length);
struct student list[length];
studentp=malloc(length*sizeof(struct student));
if (studentp==NULL)
{
printf("Out of memory!");
return 0;
}
for(i = 0; i < length; i++) {
StudentScan(i,studentp);
printf("\nEnter average number: ");
scanf("%s", list[i].AverageNum);
}
free (studentp);
void StudentScan(int i, struct student list[])
{ printf("\nEnter first name : ");
scanf("%s", list[i].firstName);
printf("\nEnter average number: ");
scanf("%s", list[i].AverageNum);
}
return 0;
}
最佳答案
发布的代码已在StudentScan()
中定义了main()
。但是C中不允许使用嵌套函数定义。这将生成编译器警告,例如:
请注意所有编译器警告并进行修复。如果在编译此代码时未看到警告,请调高编译器警告级别。在gcc上,我建议始终至少使用gcc -Wall -Wextra
,并且始终添加-Wpedantic
。 gcc需要-Wpedantic
才能看到警告。有些编译器(其中gcc就是其中之一)确实支持嵌套函数定义作为编译器扩展。不过,此功能是非标准的,最好不要依赖它。
修复很简单:将StudentScan()
的定义移出main()
:
#include <stdio.h>
#include <stdlib.h>
struct student {
char firstName[20];
char AverageNum[2];
};
void StudentScan(int, struct student[]);
void StudentPrint(int, struct student[]);
int main(void) {
int i;
int length;
struct student *studentp;
printf ("\nEnter the host of students: ");
scanf ("%d ", &length);
struct student list[length];
studentp=malloc(length*sizeof(struct student));
if (studentp==NULL)
{
printf("Out of memory!");
return 0;
}
for(i = 0; i < length; i++) {
StudentScan(i,studentp);
printf("\nEnter average number: ");
scanf("%s", list[i].AverageNum);
}
free (studentp);
return 0;
}
void StudentScan(int i, struct student list[])
{ printf("\nEnter first name : ");
scanf("%s", list[i].firstName);
printf("\nEnter average number: ");
scanf("%s", list[i].AverageNum);
}
还要注意,在使用带有
scanf()
或%s
的%[]
系列函数读取字符串时,应始终指定最大宽度,以避免缓冲区溢出。例如:scanf("%19s", list[i].firstName);
请注意,即使
firstName
字段是20个char
值的数组,也使用19。请记住,必须为\0
终止符保留一个空格。并且由于您正在使用%s
将字符串读取到AverageNum
字段中,因此您还应该具有:scanf("%1s", list[i].AverageNum);
也就是说,此字段只能保留一位数字。如果要保留两位数,则必须在
struct
中将此字段更改为:char AverageNum[3]
。在讨论
scanf()
时,请注意,此函数返回在函数调用期间进行的成功分配的次数。如果未进行分配,则返回0。应该始终检查此返回值。考虑:如果用户在期望输入数字时错误地输入了字母,则预期的变量中将不存储任何内容。这可能导致不确定的行为。您可以尝试执行以下操作来验证数字输入:printf ("\nEnter the host of students: ");
while (scanf ("%d ", &length) < 1) {
puts("Please enter a number");
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
如果期望时未输入数字,此代码将要求用户再次输入输入。请注意,如果用户确实输入了非数字,则此字符将保留在输入流中,并且在尝试处理更多用户输入之前必须将其清除。
while
循环是完成此任务的典型构造。编辑
根据OP的评论,这是发布代码的修改版本。此版本使用
float
值代替AverageNum
的struct
字段的字符数组。对于存储平均值,浮点类型可能比整数类型更有用。通常最好将double
用于浮点值,但在这种情况下,AverageNum
看起来几乎不需要精度(char
数组原本只打算容纳两位)。 float
可能足以用于此用途。如果需要使用其他类型,那么修改下面的代码就足够简单了。实现了一些输入验证,但请注意,可以做更多的工作。当发现非数字输入时,要求用户输入数字,这是希望输入数字的地方。输入错误后,将使用
while
循环结构清理输入流;例如,最好将此代码删除到一个名为clear_input()
的单独函数中。如果用户从键盘上发出文件结束信号,
scanf()
将返回EOF
;在这种情况下,以下代码选择退出并显示错误消息,而不是继续输入格式错误的代码。从文件重定向的输入也可能发生这种情况,并且如果需要这种输入,则可能需要以不同的方式处理这种情况。填充
list[]
数组的循环似乎运行效率低下,每遍请求AverageNum
两次。这已简化。请注意,对
malloc()
的调用可以重写为:studentp = malloc(length * sizeof *studentp);
这是编写此类分配的非常惯用的方式。在这里,不是使用显式类型作为
sizeof
的操作数,即代替sizeof (struct student)
,而是使用保存分配地址的变量。 sizeof
仅使用表达式*studentp
的类型,因此此处未取消引用此变量。通过这种方式进行编码,在代码的维护期内,如果类型发生更改,则不易出错,并且更易于维护。然而,目前尚不清楚为什么首先要为
studentp
分配内存。在发布的代码中,在循环中对firstName
的调用中,为动态分配的AverageNum
的成员填充了studentp
和StudentScan()
字段;相同的循环使用不同的输入填充AverageNum
成员(不同的list[]
数组)的struct
字段。似乎不需要这些student
数组struct
数组之一;我已经注释掉了动态分配的数组,以支持静态分配的版本。这是修改后的代码:
#include <stdio.h>
#include <stdlib.h>
struct student {
char firstName[20];
float AverageNum;
};
void StudentScan(int, struct student[]);
void StudentPrint(int, struct student[]);
int main(void) {
int i;
int length;
// struct student *studentp;
printf ("\nEnter the host of students: ");
while (scanf ("%d", &length) < 1) {
puts("Please enter a number");
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
struct student list[length];
/* This is fine */
// studentp = malloc(length * sizeof (struct student));
/* But this is better */
// studentp = malloc(length * sizeof *studentp);
// if (studentp == NULL)
// {
/* Not wrong, but... */
// printf("Out of memory!");
// return 0;
// fprintf(stderr, "Allocation failure\n");
// exit(EXIT_FAILURE);
// }
for(i = 0; i < length; i++) {
StudentScan(i, list);
}
/* Code to display results here */
// free (studentp);
return 0;
}
void StudentScan(int i, struct student list[])
{
putchar('\n');
printf("Enter first name: ");
if (scanf("%19s", list[i].firstName) != 1) {
puts("Input error");
exit(EXIT_FAILURE);
}
printf("Enter average number: ");
while (scanf("%f", &list[i].AverageNum) < 1) {
puts("Please enter a number");
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
}