执行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值代替AverageNumstruct字段的字符数组。对于存储平均值,浮点类型可能比整数类型更有用。通常最好将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的成员填充了studentpStudentScan()字段;相同的循环使用不同的输入填充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;
        }
    }
}

07-28 03:05