无法从 C 中的结构打印数据

Can't print data from struct in C

我的目标是打印 struct

中包含的学生数据

我的问题是为什么我无法从结构中打印出数据?

这是我的代码:

typedef struct _STUDENT{
    char *fullname;
    int ID;
    float scores[6];
} STUDENT;
void input(STUDENT* student){
    fflush(stdin);
    printf("\nInput Student Fullname: ");
    scanf("%s", &student->fullname);
    printf("\nInput ID: ");
    scanf("%s",&student->ID);
    for(int i = 0; i < 6; i++){
        printf("\nInput point for course %d: ", i+1);
        scanf("%f",&student[i].scores);
    }
    
}
void output(STUDENT* student){
    
    printf("\nStudent Fullname: %s", student->fullname);
    printf("\nStudent ID: %d", student->ID);
    for(int i = 0; i < 6; i++){
        printf("\nStudent Score: %f", student[i].scores);   
    }
    
}

int main(){
    
    STUDENT* students;
    int size;
    printf("Enter number of student: ");
    scanf("%d",&size);
    
    students = (STUDENT*)calloc(size,sizeof(STUDENT));
    
    for(int i =0;i<size;i++){

        input(students+i);
    }

    
    for(int i =0;i<size;i++){
        output(students+i);
    }
    return 0;
}

这是输出:

Student Fullname:?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Student ID: 50
Student Score: 0.000000
Student Score: 0.000000
Student Score: 0.000000
Student Score: 0.000000
Student Score: 0.000000
Student Score: 0.000000

在输出功能下,我尝试打印出一些数据,但 none 已经打印出来了

My question is why i unable to print out data from struct?

在某种程度上,由于 input() 函数中的许多错误,学生数据不是您所期望的。您可能已经通过 运行 调试器控制下的程序自己发现了这一点,并且您的编译器可能已经警告过您一些错误,至少如果您调高了警告级别。 始终注意编译器警告。

您的 input() 函数的问题包括:

  • 不要fflush()标准输入。刷新是关于输出,而不是输入。如果 fflush(stdin) 恰好产生了您认为理想的效果,那么该效果不可移植。如果您想忽略某些输入,请 阅读 并丢弃它。

    但是,只要您使用 scanffscanf 作为输入,请注意大多数字段指令会跳过前导白色 space,包括换行符。然而,在那种情况下,还要注意这些功能很难正确使用。 fgets()sscanf() 相结合可能会更好地为您服务,尽管这不是万灵药。

  • 您没有检查 scanf() 调用的 return 值。这本身并不是错误 本身 ,但它意味着程序将无法识别输入错误或格式错误的输入(相对于您的 scanf 调用序列)。

  • 这个...

        scanf("%s", &student->fullname);
    

    ... 尝试将名称读入指针的表示形式。如果名称(以 null 结尾)比指针的表示长(可能是四个或八个字节),则会导致未定义的行为。您可能打算将数据读入指针指向的位置:

        scanf("%s", student->fullname);
    

    ...但这也有问题,因为指针没有指向有效存储。您可以通过将 fullname 成员声明为数组而不是指针来解决后一个问题(使用更正的代码),在这种情况下,您需要注意避免超过 运行 的长度大批。或者,您可以将名称读入本地临时数组,然后为学生分配一个副本以指向:

    char temp[1024];
    int result = scanf("%1023s", temp);
    if (result != 1) /* ... handle input failure ... */;
    student->fullname = malloc(strlen(temp) + 1);
    strcpy(student->fullname, temp);
    

    如果你有一个 POSIX 兼容的 strdup() 函数,那么你可以使用它来代替显式的 mallocstrcpy.

  • 此外,“fullname”建议一个可能包含 space 个字符的字符串,但 %s 扫描 whitespace-delimited 字符串。您可能需要一个 %[ 指令,但请注意,这是为数不多的不忽略前导白色 space.

    的指令之一
  • 这个...

        scanf("%s",&student->ID);
    

    ... 是错误的,因为 &student->ID 是指向 int 的指针,而 %s 需要指向 char 的指针。此外,这将尝试将结果存储为字符串,而不是 int.

  • 这个...

                scanf("%f",&student[i].scores);
    

    ... 是错误的,因为您传递的是指向数组(float)的指针,而不是指向 float 的指针。这本身在实践中可能不会导致错误,但对于 i != 0,它也是指向错误位置的指针。 student[i].scores 是偏移 i 处学生的 scores 数组,但您似乎想要分数的第 ith 元素偏移量为 0 的学生数组:

                scanf("%f", &student->scores[i]);
    

    与此类似的错误也出现在您的 output() 函数中。

    此外,如果您正在检查,那么您可能会发现这些调用中的一些或所有都无法扫描任何内容。使用您当前的代码,当出现由三部分组成的全名(例如,“Cento T. Programmer”)时,可能会出现这种情况。