You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;}

问题根源

  1. 排序循环逻辑错误:原代码的双层循环不符合冒泡排序逻辑,内层遍历所有元素会导致重复交换,无法完成正确升序排序。
  2. 成绩比较方式错误:将成绩存为字符串后用>比较的是内存地址而非数值大小,排序结果不符合预期。
  3. 结构体交换繁琐易出错:逐个复制字符串字段容易遗漏,效率低下。
  4. 搜索函数越界风险:未找到目标时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;
}

关键修改说明

  1. 结构体字段调整:将marks改为int类型,彻底解决字符串比较数值的错误,简化输入和排序逻辑。
  2. 排序逻辑重构:采用标准冒泡排序的双层循环,内层遍历范围逐步缩小,确保每次将最大元素移到末尾,实现正确升序排序。
  3. 结构体交换优化:直接交换整个结构体变量,替代逐个复制字符串的繁琐操作,减少出错概率。
  4. 搜索函数边界修复:通过判断i是否等于n确定是否找到目标,避免数组越界访问。
  5. 输入逻辑优化:用getchar()替代未定义行为的fflush(stdin),处理输入缓冲区的换行符,避免后续输入异常。

内容的提问来源于stack exchange,提问作者Hadiya Kashif

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 02:40:54