我正在编写一个带有结构和指针的程序。正如您将在程序中看到的,我询问用户是否想继续添加学生。我想检查他的答案是
Yes
还是No
。显然我做错了什么,因为我的程序在他回答后完成。所以我需要帮助来发现错误并找到正确编写代码的方法。
我还想问为什么
number[i].age
需要在&
中的字体中添加scanf
。我的意思是它是一个指针,所以为什么要使用 &
?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct student {
char name[30];
int age;
}student ;
int main(){
typedef int size;
int i;
size siz=0;
student *number;
printf("Welcome\n\nEnter the number of student you want to evaluate: ");
scanf("%d",&siz);
printf("\n");
number=malloc(siz*(sizeof(struct student)));
for(i=0;i<siz;i++){
printf("Student name: ");
scanf("%s",number[i].name);
printf("Student age: ");
scanf("%d",&number[i].age);
printf("\n");
}
printf("Do you want to add Students(Yes or No)? ");
void * answer;
scanf("%s",*answer);
if(strcmp(answer, "Yes")==0){
printf("\n Give the number of the additional students: ");
int adsize;
scanf("%d",&adsize);
student*realloc=(number,adsize*sizeof(int));
int j=0;
for(j=0;j<adsize;j++){
printf("Student name: ");
scanf("%c",number[j].name);
printf("Student age: ");
scanf("%d",number[j].age);
printf("\n");
}
}
else
printf("\nEnd of programm");
return 0;
}
您必须学会正确缩进代码,以便您和其他人获得可读性。
这是代码的重新格式化版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
char name[30];
int age;
} student;
int main() {
typedef int size;
int i;
size siz = 0;
student *number;
printf("Welcome\n\nEnter the number of student you want to evaluate: ");
scanf("%d", &siz);
printf("\n");
number = malloc(siz * (sizeof(struct student)));
for (i = 0; i < siz; i++) {
printf("Student name: ");
scanf("%s", number[i].name);
printf("Student age: ");
scanf("%d", &number[i].age);
printf("\n");
}
printf("Do you want to add Students(Yes or No)? ");
void *answer;
scanf("%s", *answer);
if (strcmp(answer, "Yes") == 0) {
printf("\n Give the number of the additional students: ");
int adsize;
scanf("%d", &adsize);
student *realloc = (number, adsize * sizeof(int));
int j = 0;
for (j = 0; j < adsize; j++) {
printf("Student name: ");
scanf("%c", number[j].name);
printf("Student age: ");
scanf("%d", number[j].age);
printf("\n");
}
} else
printf("\nEnd of programm");
return 0;
}
有些问题立即出现:
typedef int size;
在函数 main
中定义了具有局部作用域的类型。避免这种令人困惑且容易出错的定义。
在
scanf("%d", &siz)
中,您没有测试scanf()
的返回值。这是有风险的,因为无效或丢失的输入将被忽略,如果代码后面没有未定义的行为,则会导致意外的行为。 始终测试并报告无效或丢失的输入:
if (scanf("%d", &siz) != 1) {
fprintf(stderr, "invalid or missing input\n");
exit(1);
}
您使用
malloc
分配内存,但不检查分配失败。测试和报告内存分配失败也将有助于跟踪问题。
scanf("%s", number[i].name);
不需要 &
,因为 number[i].name
是一个数组,并且数组始终作为指向其第一个元素的指针传递。然而,这个 scanf()
调用是有风险的,因为您没有为 scanf()
提供防止超长输入缓冲区溢出的方法。用这个代替:
if (scanf("%29s", number[i].name) != 1) {
fprintf(stderr, "invalid or missing input for number[%d].name\n", i);
exit(1);
}
scanf("%d", &number[i].age);
需要&
,因为number[i].age
是int
成员,您必须将其地址传递给scanf
才能存储转换后的值。当然,您必须测试返回值以检测并报告无效或丢失的输入。
void *answer; scanf("%s", *answer);
完全是假的:您取消引用 void
指针,该指针无法在标准 C 中编译(您的编译器可能支持它的扩展)并且 answer
无论如何都未初始化,因此取消引用指针可能具有未定义的行为分段错误,这会导致您的程序按观察到的方式停止。你应该这样写:
char answer[10];
if (scanf("%9s", answer) != 1 || strcmp(answer, "Yes")) {
printf("end of program\n");
return 0;
}
student*realloc=(number,adsize*sizeof(int));
是最惊喜的!它实际上被解析为
student *realloc = (number, adsize * sizeof(int));
它将局部变量
realloc
定义为指向 student
的指针,通过将 adsize * sizeof(int)
转换为指针进行初始化...毫无意义,并且对 number
指向的数组没有副作用。
您绝对应该使用额外的警告进行编译,以使用 gcc -Wall -Wextra -Werror 或编译器的类似选项来检测此类错误。