C语言学生信息按成绩升序排序异常问题求助
学生成绩排序问题修复
问题概述
需要实现一个C语言程序,完成以下功能:
- 录入学生的姓名、成绩、学号信息
- 按成绩升序排序学生数据
- 分别按学号和姓名查询学生信息
当前程序的搜索功能正常,但排序函数仅在录入2名学生时能正确工作,录入超过2名学生时排序结果错误,需修复该问题。
原代码
#include<stdio.h> #include<string.h> struct data{ char roll_No[5],name[15],marks[5]; }; struct data stInfo[50]; struct data temp[50]; void sortMarks(int n, struct data *stInfo){ int i,j; for(i=0;i<n;i++){ for(j=0;j<n;j++){ if(stInfo[i].marks>stInfo[j].marks){ strcpy(temp[i].marks,stInfo[i].marks); strcpy(stInfo[i].marks,stInfo[j].marks); strcpy(stInfo[j].marks,temp[i].marks); strcpy(temp[i].name,stInfo[i].name); strcpy(stInfo[i].name,stInfo[j].name); strcpy(stInfo[j].name,temp[i].name); strcpy(temp[i].roll_No,stInfo[i].roll_No); strcpy(stInfo[i].roll_No,stInfo[j].roll_No); strcpy(stInfo[j].roll_No,temp[i].roll_No);}}} for(i=0;i<n;i++){ printf("\nAfter sorting data of student %d:\n%s,%s,%s\n",i+1,stInfo[i].name,stInfo[i].roll_No,stInfo[i].marks);} return;} void searchRoll_No(int n,char *roll_NoToFind, struct data *stInfo){ int i; for(i=0;i<n;i++){ if(!strcmp(roll_NoToFind,stInfo[i].roll_No)){ printf("The student is: %s having marks: %s\n",stInfo[i].name,stInfo[i].marks); break;}} if(strcmp(roll_NoToFind,stInfo[i].roll_No)){ printf("Record not found!\n");} return;} void searchName(int n,char *nameToFind, struct data *stInfo){ int i; for(i=0;i<n;i++){ if(!strcmp(nameToFind,stInfo[i].name)){ printf("The student has roll no: %s and marks: %s\n",stInfo[i].roll_No,stInfo[i].marks); break;}} if(strcmp(nameToFind,stInfo[i].name)){ printf("Record not found!\n");} return;} int main(){ int n,i; printf("Enter the number of students: \n"); scanf("%d",&n); for(i=0;i<n;i++){ printf("Enter roll no of student %d: \n",i+1); scanf("%s",&stInfo[i].roll_No); printf("Enter name of student %d: \n",i+1); scanf("%s",&stInfo[i].name); fflush(stdin); printf("Enter marks of student %d: \n",i+1); scanf("%s",&stInfo[i].marks);} sortMarks(n,stInfo); char roll_NoToFind[5]; printf("\nEnter the roll number you want to search: \n"); scanf("%s",&roll_NoToFind); fflush(stdin); searchRoll_No(n,roll_NoToFind,stInfo); char nameToFind[15]; printf("\nEnter the name you want to search: \n"); scanf("%s",&nameToFind); fflush(stdin); searchName(n,nameToFind,stInfo); return 0;}
问题根源
- 排序循环逻辑错误:原代码的双层循环不符合冒泡排序逻辑,内层遍历所有元素会导致重复交换,无法完成正确升序排序。
- 成绩比较方式错误:将成绩存为字符串后用
>比较的是内存地址而非数值大小,排序结果不符合预期。 - 结构体交换繁琐易出错:逐个复制字符串字段容易遗漏,效率低下。
- 搜索函数越界风险:未找到目标时
i等于n,访问stInfo[i]会触发数组越界,属于未定义行为。
修复后的代码
#include<stdio.h> #include<string.h> // 调整结构体,将marks改为int类型便于数值比较 struct data{ char roll_No[5]; char name[15]; int marks; }; struct data stInfo[50]; // 标准冒泡排序,按成绩升序排列 void sortMarks(int n, struct data *stInfo){ int i, j; struct data temp; for(i=0; i<n-1; i++){ // 内层循环遍历未排序区间,逐步缩小范围 for(j=0; j<n-i-1; j++){ // 直接比较成绩数值 if(stInfo[j].marks > stInfo[j+1].marks){ // 交换整个结构体,简洁高效 temp = stInfo[j]; stInfo[j] = stInfo[j+1]; stInfo[j+1] = temp; } } } // 输出排序结果 for(i=0; i<n; i++){ printf("\nAfter sorting data of student %d:\n%s,%s,%d\n", i+1, stInfo[i].name, stInfo[i].roll_No, stInfo[i].marks); } } // 按学号查询,修复越界问题 void searchRoll_No(int n, char *roll_NoToFind, struct data *stInfo){ int i; for(i=0; i<n; i++){ if(!strcmp(roll_NoToFind, stInfo[i].roll_No)){ printf("The student is: %s having marks: %d\n", stInfo[i].name, stInfo[i].marks); break; } } // 通过i是否等于n判断是否找到,避免越界 if(i == n){ printf("Record not found!\n"); } } // 按姓名查询,修复越界问题 void searchName(int n, char *nameToFind, struct data *stInfo){ int i; for(i=0; i<n; i++){ if(!strcmp(nameToFind, stInfo[i].name)){ printf("The student has roll no: %s and marks: %d\n", stInfo[i].roll_No, stInfo[i].marks); break; } } if(i == n){ printf("Record not found!\n"); } } int main(){ int n, i; printf("Enter the number of students: \n"); scanf("%d", &n); getchar(); // 处理scanf后的换行符 for(i=0; i<n; i++){ printf("Enter roll no of student %d: \n", i+1); scanf("%s", stInfo[i].roll_No); printf("Enter name of student %d: \n", i+1); scanf("%s", stInfo[i].name); printf("Enter marks of student %d: \n", i+1); scanf("%d", &stInfo[i].marks); getchar(); // 处理输入后的换行符 } sortMarks(n, stInfo); char roll_NoToFind[5]; printf("\nEnter the roll number you want to search: \n"); scanf("%s", roll_NoToFind); searchRoll_No(n, roll_NoToFind, stInfo); char nameToFind[15]; printf("\nEnter the name you want to search: \n"); scanf("%s", nameToFind); searchName(n, nameToFind, stInfo); return 0; }
关键修改说明
- 结构体字段调整:将
marks改为int类型,彻底解决字符串比较数值的错误,简化输入和排序逻辑。 - 排序逻辑重构:采用标准冒泡排序的双层循环,内层遍历范围逐步缩小,确保每次将最大元素移到末尾,实现正确升序排序。
- 结构体交换优化:直接交换整个结构体变量,替代逐个复制字符串的繁琐操作,减少出错概率。
- 搜索函数边界修复:通过判断
i是否等于n确定是否找到目标,避免数组越界访问。 - 输入逻辑优化:用
getchar()替代未定义行为的fflush(stdin),处理输入缓冲区的换行符,避免后续输入异常。
内容的提问来源于stack exchange,提问作者Hadiya Kashif
相关产品推荐
相关产品推荐

