国名排序题笔记(字符串函数 + fgets 详解)

一、题目需求

输入n个国家名称,读取后按字典序升序 排序,最终输出排序后的结果。

核心难点:正确读取字符串(处理换行符)、使用字符串函数实现排序逻辑。

二、核心知识点拆解

1. fgets:安全读取字符串

(1)函数原型
c 复制代码
char *fgets(char *str, int n, FILE *stream);
(2)参数说明
  • str:存储读取到的字符串的数组(比如本题的countries[i]);
  • n:最多读取的字符数(包含末尾的\0,实际读取n-1个字符);
  • stream:输入流,读取控制台输入用stdin
(3)关键特性(本题必知)

✅ 优点:比scanf("%s")安全,能读取带空格的字符串(比如United States),且不会数组越界;

❌ 注意:读取时会把输入末尾的换行符\n 一起存入字符串(比如输入China+回车,实际存入"China\n"),需手动清理。

(4)本题用法
c 复制代码
// 读取第i个国家名称,最多读MAX_LEN-1个字符
fgets(countries[i], MAX_LEN, stdin);

2. strcspn:清理换行符的核心

(1)函数原型
c 复制代码
size_t strcspn(const char *str1, const char *str2);
(2)作用

计算str1第一个出现在str2字符集合里的字符的位置 (下标),返回该位置值。

👉 本题中:strcspn(countries[i], "\n") → 找到countries[i]\n的下标。

(3)本题核心用法(清理换行符)
c 复制代码
// 找到\n的位置,替换为\0(字符串结束符),截断换行符
countries[i][strcspn(countries[i], "\n")] = '\0';

⚠️ 易错点:第二个参数必须是字符串"\n" ,而非单个字符'\n'(类型不匹配会编译/运行错误)。

3. strcmp:字符串比较(排序的核心)

(1)函数原型
c 复制代码
int strcmp(const char *str1, const char *str2);
(2)返回值(字典序比较)
  • 返回>0str1字典序 > str2(比如"Japan" > "China");
  • 返回=0str1str2完全相同;
  • 返回<0str1字典序 < str2
(3)本题用法(冒泡排序判断条件)
c 复制代码
// 若前一个字符串字典序更大,交换两者(实现升序)
if(strcmp(countries[j], countries[j+1]) > 0) {
    // 交换逻辑
}

4. strcpy:字符串拷贝(交换字符串)

(1)函数原型
c 复制代码
char *strcpy(char *dest, const char *src);
(2)作用

src指向的字符串拷贝到dest中(包含\0),需保证dest数组容量足够。

(3)本题用法(冒泡排序交换元素)
c 复制代码
char temp[MAX_LEN]; // 临时数组存交换的字符串
strcpy(temp, countries[j]);       // 把前一个字符串存到temp
strcpy(countries[j], countries[j+1]); // 后一个覆盖前一个
strcpy(countries[j+1], temp);     // temp覆盖后一个

三、完整代码(带详细注释)

c 复制代码
#include<stdio.h>
#include<string.h>
#define MAX_LEN 50          // 单个国名最大长度
#define MAX_COUNTRIES 110   // 最多国名数量

int main()
{
    int n;
    // 输入合法性检查:避免非数字/超出范围的n
    if (scanf("%d", &n) != 1 || n < 1 || n > MAX_COUNTRIES) {
        printf("输入数量不合法!\n");
        return 1;
    }
    getchar(); // 吸收scanf残留的换行符(否则fgets会读空行)

    char countries[MAX_COUNTRIES][MAX_LEN]; // 存储国名的二维数组
    char temp[MAX_LEN]; // 交换用的临时数组

    // 1. 读取n个国名,清理换行符
    for(int i = 0; i < n; i++)
    {
        fgets(countries[i], MAX_LEN, stdin); // 读取一行字符串
        // 关键:用strcspn找到\n的位置,替换为\0去掉换行符
        countries[i][strcspn(countries[i], "\n")] = '\0';
    }

    // 2. 冒泡排序:按字典序升序排列
    for(int i = 0; i < n - 1; i++) // 排序轮数:n-1轮
    {
        for(int j = 0; j < n - i - 1; j++) // 每轮比较次数递减
        {
            // strcmp比较两个字符串,前大后小则交换
            if(strcmp(countries[j], countries[j+1]) > 0)
            {
                strcpy(temp, countries[j]);
                strcpy(countries[j], countries[j+1]);
                strcpy(countries[j+1], temp);
            }
        }
    }

    // 3. 输出排序结果
    for(int i = 0; i < n; i++)
    {
        printf("%s\n", countries[i]);
    }

    return 0;
}

四、常见错误避坑

  1. fgets读取空行scanf("%d", &n)后未加getchar(),残留的换行符会被fgets读取,导致第一个字符串为空;
  2. strcspn参数错误 :把"\n"写成'\n'(字符 vs 字符串,类型不匹配);
  3. 数组越界 :未检查n的范围(比如n>110),导致访问countries数组超出定义长度;
  4. strcmp使用错误 :误以为返回1/-1,实际返回任意正/负数,只需判断>0/<0即可。

五、核心总结

  1. fgets :安全读取带空格的字符串,但会读取换行符,需用strcspn清理;
  2. strcspn :快速定位目标字符(如\n)的位置,是处理fgets换行符的最优方式;
  3. strcmp:字符串比较的核心函数,字典序排序的关键,返回值判断大小关系;
  4. strcpy:字符串拷贝工具,需配合临时数组实现字符串交换(二维字符串数组无法直接赋值)。

这套组合是C语言字符串处理的经典用法,尤其适用于"读取-处理-排序-输出"类字符串题目。

相关推荐
四谎真好看2 小时前
Redis学习笔记(实战篇3)
redis·笔记·学习·学习笔记
bennybi2 小时前
Openclaw 实践笔记
笔记·ai·openclaw
AI视觉网奇2 小时前
aigc 生成几何图 整理笔记
笔记·aigc
今儿敲了吗2 小时前
python基础学习笔记第五章——容器
笔记·python·学习
三水不滴3 小时前
Elasticsearch 实战系列(二):SpringBoot 集成 Elasticsearch,从 0 到 1 实现商品搜索系统
经验分享·spring boot·笔记·后端·elasticsearch·搜索引擎
Ynchen. ~3 小时前
快速复习笔记(随笔)
笔记
chikaaa3 小时前
RabbitMQ 核心机制总结笔记
java·笔记·rabbitmq·java-rabbitmq
C羊驼4 小时前
C 语言:哥德巴赫猜想
c语言·开发语言·人工智能·经验分享·笔记·算法·课程设计
qcwl664 小时前
深入理解Linux进程与内存 学习笔记#1
笔记·学习