执行exe后,我收到此错误:
未定义参考`StudentScan'
错误:ld返回1退出状态|
注意:我对编码很不好,所以请不要介意我的编码错误^^ 注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;
}
答案 0 :(得分:1)
已发布的代码已在StudentScan()
中定义main()
。但是C中不允许嵌套函数定义。这应该生成编译器警告,例如:
警告:ISO C禁止嵌套函数[-Wpedantic]
void StudentScan(int i,struct student list [])
注意所有编译器警告并修复它们。如果在编译此代码时未看到警告,请调高编译器警告的级别。在gcc上,我建议始终至少使用gcc -Wall -Wextra
,并且我总是添加-Wpedantic
。 gcc需要-Wpedantic
才能看到此警告。一些编译器和gcc就是其中之一, do 支持嵌套函数定义作为编译器扩展。尽管如此,这个功能还是非标准的,最好不要依赖它。
修复很简单:将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
的{{1}}族函数读取字符串时,应始终指定最大宽度,以避免缓冲区溢出。例如:
%[]
请注意,即使scanf("%19s", list[i].firstName);
字段是包含20个firstName
值的数组,也会使用19。请记住,必须为char
终结符保留一个空格。由于您使用\0
将字符串读入%s
字段,因此您还应该:
AverageNum
也就是说,这个字段只能容纳一位数。如果打算保留两位数,则必须在scanf("%1s", list[i].AverageNum);
内将此字段更改为:struct
。
在我们讨论char AverageNum[3]
时,请注意此函数返回函数调用期间成功分配的次数。如果未进行任何分配,则返回0。应该总是检查此返回值。考虑:如果用户在预期数字时错误地输入了一个字母,则没有任何内容存储在预期的变量中。这可能会导致未定义的行为。您可以尝试这样的方法来验证数字输入:
scanf()
如果在预期时未输入数字,此代码会要求用户再次输入输入。请注意,如果用户 输入非数字,则此字符将保留在输入流中,并且必须先清除,然后再尝试处理更多用户输入。 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;
}
}
循环是完成此任务的典型构造。
根据OP的评论,这里是已发布代码的修改版本。对于while
的{{1}}字段,此版本使用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
s的不同数组)。似乎不需要其中一个list[]
struct
s阵列;我已经注释掉动态分配的数组,转而使用静态分配的版本。
以下是修改后的代码:
student
答案 1 :(得分:0)
您必须从主屏幕中删除扫描功能。此外,您没有声明的printstudent功能。您必须从printf和scanf函数中删除/ n并相应地放置它们。然后,您可以使用简单的循环测试是否在结构中正确添加了数据。
#include <stdio.h>
#include <stdlib.h>
struct student {
char firstName[20];
char AverageNum[2];
};
int main() {
int i=0;
int length;
struct student *studentp;
printf ("Enter 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++) {
printf("Enter first name :");
scanf("%s", list[i].firstName);
printf("Enter average number: ");
scanf("%1s", list[i].AverageNum);
}
for(i = 0; i< length; i++){
printf("number of host is: %d , his/her first name: %s , his/her avg number: %s \n", i, list[i].firstName, list[i].AverageNum);
}
free (studentp);
return 0;
}