C语言学生录入程序应读取11组输入仅执行1次就终止问题排查
问题原因分析
错误1:
scanf读取int类型时未传递内存地址scanf的%d格式符要求传入对应int变量的指针(即内存地址),才能把用户输入的值写入对应的变量空间。你代码中读取出生日期的行已经被编译器明确告警问题所在:format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’,你直接传递了int类型的成员值,相当于把这三个成员里的随机垃圾值当成内存地址,scanf尝试往非法地址写数据,触发段错误,直接导致程序异常终止,这是程序跑一次就退出的直接原因。
修正方法是给三个参数都加上取地址符&:scanf("%d %d %d", &BIM[i].DOB.year, &BIM[i].DOB.month, &BIM[i].DOB.day);错误2:数组越界访问
你定义的struct student BIM[10];是长度为10的数组,合法索引范围是0~9,但你的循环写的是for(i=0;i<11;i++),会尝试访问BIM[10]这个不存在的元素,也会触发非法内存访问,就算第一个问题修好,程序也会出现不可预期的错误。
修正方法要么把数组定义改成struct student BIM[11];,要么把循环条件改成i < 10。
额外优化建议
scanf读取字符串时建议增加长度限制,避免用户输入过长导致缓冲区溢出,例如读取name时用%24s,读取city、district时用%14s,程序安全性会更高。
修正后完整代码
#include <stdio.h> int main() { struct date { int year; int month; int day; }; struct address { char city[15]; char district[15]; }; struct student { char name[25]; int roll_no; struct date DOB; struct address add; }; // 数组长度改为11匹配循环次数 struct student BIM[11]; int i; for(i=0;i<11;i++) { printf("Enter student name: "); scanf("%24s",BIM[i].name); printf("Enter roll no: "); scanf("%d",&BIM[i].roll_no); printf("Enter Date of birth: "); // 补充取地址符 scanf("%d %d %d", &BIM[i].DOB.year, &BIM[i].DOB.month, &BIM[i].DOB.day); printf("Enter address: "); scanf("%14s %14s",BIM[i].add.district,BIM[i].add.city); } int roll; printf("Enter roll no: "); scanf("%d",&roll); for(i=0;i<11;i++) { if(roll==BIM[i].roll_no) { printf("Name : %s\n",BIM[i].name); printf("Roll no : %d\n",BIM[i].roll_no); printf("DOB : %d/%d/%d\n",BIM[i].DOB.year,BIM[i].DOB.month,BIM[i].DOB.day); printf("Address : %s,%s\n",BIM[i].add.district,BIM[i].add.city); break; } } return 0; }
内容的提问来源于stack exchange,提问作者Ayush Bajracharya
相关产品推荐
相关产品推荐

