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

按学生姓氏字母序排序数组的C代码输入输出异常排查

问题分析与修复:无法输入多个学生姓名及排序异常的C代码问题

一、输入异常的核心原因

  1. fflush(stdin)是未定义行为
    C标准明确规定fflush只能用来刷新输出流的缓冲区,对输入流调用它属于错误操作,不同编译器的处理逻辑完全不一致。这会导致输入完学生数量n后,缓冲区里残留的换行符没被正确清理,后续输入函数要么读到空内容,要么直接打乱整个输入流程。

  2. gets()函数不安全且已被废弃
    gets()完全不检查输入长度,当你输入像"Nihan ahmed"这种超过8个字符的名字时,会直接溢出你定义的name[10][8]缓冲区,破坏程序的内存结构,导致程序异常卡死,没法继续接收下一个名字。而且这个函数在C11标准里已经被彻底移除了,绝对不要使用它。

  3. 数组存储空间严重不足
    你定义的每个学生名字数组只有8个字节,去掉字符串终止符\0,最多只能存7个字符,显然不够存储带空格的全名,这也是缓冲区溢出的直接诱因。

二、排序逻辑的致命问题

  1. 寻找空格的循环逻辑错误
    你的代码里k初始为0,先执行++k再判断是否为空格,这直接跳过了名字的第一个字符。如果遇到没有空格的名字,这个循环会无限执行,越界访问数组内存,触发不可预测的未定义行为。

  2. 排序逻辑不完整且错误
    你只实现了冒泡排序的皮毛,没有多轮遍历完成完整排序;而且只比较了空格后的第一个字符,没有完整比较姓氏的字典序,最终的排序结果肯定不符合预期。

三、修正后的可运行代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main() {
    // 增大数组大小,足够存储常见的全名
    char name[10][50], temp[50];
    int i, j, n;

    printf("Enter the number of students:\n");
    // 用scanf读取n后,手动清理缓冲区的换行符
    scanf("%d", &n);
    // 跳过输入缓冲区里的换行和空白字符
    while(getchar() != '\n');

    printf("\nPlease enter the names of the students:\n");
    for(i = 0; i < n; i++) {
        // 用fgets代替gets,安全且能读取带空格的字符串
        fgets(name[i], sizeof(name[i]), stdin);
        // 去掉fgets读取到的换行符
        name[i][strcspn(name[i], "\n")] = '\0';
    }

    // 冒泡排序:按姓氏(空格后的部分)排序,没有空格则按全名排序
    for(i = 0; i < n - 1; i++) {
        for(j = i + 1; j < n; j++) {
            // 找到每个名字里空格的位置
            char *lastNameI = strchr(name[i], ' ');
            char *lastNameJ = strchr(name[j], ' ');
            
            // 如果有空格,用姓氏比较;否则用全名比较
            const char *cmpStrI = lastNameI ? lastNameI + 1 : name[i];
            const char *cmpStrJ = lastNameJ ? lastNameJ + 1 : name[j];

            if(strcmp(cmpStrI, cmpStrJ) > 0) {
                strcpy(temp, name[i]);
                strcpy(name[i], name[j]);
                strcpy(name[j], temp);
            }
        }
    }

    printf("After sorting the array:\n");
    for(i = 0; i < n; i++) {
        puts(name[i]);
    }

    return 0;
}

关键修正点说明

  • 用while(getchar() != '\n')代替fflush(stdin),安全清理输入缓冲区的换行符,避免跨编译器的兼容性问题。
  • 改用fgets()读取字符串,自动限制输入长度,避免缓冲区溢出,同时手动去掉读取到的换行符,保证字符串格式正确。
  • 增大了名字数组的大小,足够存储带空格的全名。
  • 用strchr()找空格位置,逻辑更简洁安全;用strcmp()完整比较字符串的字典序,实现了正确的冒泡排序逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 20:47:40