strcmp函数和strcpy函数

strcmp
 
  原型:extern int strcmp(char *s1,char * s2);
        
  用法:#include <string.h>
  
  功能:比较字符串s1和s2。
  
  说明:
        当s1<s2时,返回值<0
        当s1=s2时,返回值=0
        当s1>s2时,返回值>0
  
实际上,字符串的比较是比较字符串中各对字符的ASCII码。
首先比较两个串的第一个字符,若不相等,则停止比较并得出大于或小于的结果;
如果相等就接着 比较第二个字符然后第三个字符等等。如果两上字符串前面的字符一直相等,像"abcd"和"abcde"   那样,   
前四个字符都一样,   然后比较第 五个字符,   前一个字符串"abcd"只剩下结束符'/0',
后一个字符串"abcde"剩下'e','/0'的ASCII码小于'e'的ASCII 码,所以得出了结果。
因此无论两个字符串是什么样,strcmp函数最多比较到其中一个字符串遇到结束符'/0'为止,就能得出结果。  举例:

      // strcmp.c
      
      #include <stdlib.h>
      #include <stdio.h>
      #include <string.h>

      int main()
      {
        char *s1="Hello, World!";
        char *s2="Hello, BeiJing!";
        int r;
        
        r=strcmp(s1,s2);
        if(!r)
          printf("s1 and s2 are identical");
        else
        if(r<0)
          printf("s1 less than s2");
        else
          printf("s1 greater than s2");
       
        return EXIT_SUCCESS;
      }
stpcpy
 
  原型:extern char *stpcpy(char *dest,char *src);
        
  用法:#include <string.h>
  
  功能:把src所指由NULL结束的字符串复制到dest所指的数组中。
  
  说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
        返回指向dest结尾处字符(NULL)的指针。
  
  举例:


      // stpcpy.c
      
      #include <stdlib.h>
      #include <stdio.h>
      #include <string.h>

      int main()
      {
        char *s="Hello, World!";
        char a[20];
        
        
        strcpy(a,s);
        printf("%s",a);
 
        return EXIT_SUCCESS;
      }
# 题目重述 你希望深入了解 C 语言中的两个字符串处理函数:`strcmp` `strcpy`,结合你在代码中使用它们的方式,以及我之前指出的错误(如未加 `\0` 导致越界、`qsort` 配合 `strcmp` 的问题等),并联系到 `qsort` 中如何用 `strcmp` 实现字典序排序。 我们将从功能、常见误用、与 `\0` 的关系、在 `qsort` 中的应用等多个维度详细讲解。 --- # 详解 ## 一、`strcpy`:字符串复制函数 ### ✅ 正确定义与用途 ```c char *strcpy(char *dest, const char *src); ``` 作用:**将 `src` 字符串(包括结尾的 `\0`)复制到 `dest` 缓冲区中**。 例如: ```c char dest[10]; strcpy(dest, "abc"); // dest 现在是 {'a','b','c','\0'} ``` ### ❌ 常见错误(正是你之前犯过的) ```c char temp[5]; temp[0] = 'a'; temp[1] = 'b'; temp[2] = 'c'; // 没有写 temp[3] = '\0' strcpy(dest, temp); // ❌ 危险!strcpy 不知道哪里结束 ``` 👉 `strcpy` 会一直复制,直到遇到第一个 `\0` 为止。如果没有 `\0`,它就会读取 `temp` 后面的内存垃圾,造成**缓冲区溢出**或**未定义行为**。 ✅ 正确做法: ```c temp[3] = '\0'; // 手动补上结束符 strcpy(dest, temp); ``` --- ## 二、`strcmp`:字符串比较函数 ### ✅ 正确定义与用途 ```c int strcmp(const char *s1, const char *s2); ``` 返回值: - `< 0`:`s1 < s2`(字典序) - `== 0`:`s1 == s2` - `> 0`:`s1 > s2` 比较规则:逐字符比较 ASCII 值,直到出现不同或遇到 `\0`。 例如: ```c strcmp("apple", "banana"); // 返回负数('a'<'b') strcmp("hello", "hello"); // 返回 0 strcmp("hi", "he"); // 返回正数('i'>'e') ``` ### ❌ 错误使用场景(你在 `qsort` 中的问题) 你曾这样写: ```c char arr[120000][len]; // len 是变量,比如 5 qsort(arr, count, len, cmp); int cmp(const void *a, const void *b) { return strcmp((char*)a, (char*)b); // ❌ 危险! } ``` #### 问题在哪? - `arr[i]` 是一个长度为 `len` 的字符数组,比如 `len=5` - 你存的是 `"abcd"`,但它在内存中是 `'a','b','c','d'`,不一定有 `\0`! - 如果 `arr[i] = {'a','b','c','d','e'}`(刚好填满),没有 `\0` - `strcmp(arr[i], arr[j])` 会越过数组边界继续读,直到碰到 `\0` —— 可能在下一行数据里! ➡️ 导致: - 比较结果错误 - 程序崩溃(段错误) - 排序混乱 --- ### ✅ 如何安全地使用 `strcmp`? 必须保证每个字符串都以 `\0` 结尾! 解决方案: 1. 分配足够空间,留出 `\0` 位置; 2. 提取子串后立即添加 `\0`。 例如: ```c char temp[100]; for (int j = 0; j < i; j++) { temp[j] = a[p + j]; } temp[i] = '\0'; // ✅ 关键一步! ``` 这样 `strcpy` `strcmp` 才能安全工作。 --- ## 三、`qsort` + `strcmp`:实现字典序排序 你想对一堆字符串进行排序,常用方法是: ```c qsort(strings, n, sizeof(strings[0]), cmp); ``` 其中 `strings` 是二维数组或指针数组。 ### ✅ 正确比较函数(用于二维数组) ```c int cmp(const void *a, const void *b) { return strcmp((const char*)a, (const char*)b); } ``` ⚠️ 注意:这里的 `a` `b` 是指向某个字符串的指针(类型为 `char (*)[SIZE]`),传给 `strcmp` 前转成 `char*` 即可。 但前提:每个字符串都必须以 `\0` 结尾! ### 🔄 替代方案(更安全,不用 `\0`) 如果你不想依赖 `\0`,可以用固定长度比较: ```c int cmp_fixed(const void *a, const void *b) { return strncmp((const char*)a, (const char*)b, max_len); } ``` 或者手动比较前 `n` 个字符: ```c int cmp_manual(const void *a, const void *b) { const char *s1 = (const char*)a; const char *s2 = (const char*)b; for (int i = 0; i < len; i++) { if (s1[i] != s2[i]) return s1[i] - s2[i]; } return 0; } ``` 这种方式不需要 `\0`,适用于固定长度的字符块(如你原来的 `char arr[N][len]`)。 --- ## 四、总结对比 | 函数 | 依赖 `\0`? | 安全条件 | 常见错误 | |------|-------------|----------|---------| | `strcpy(dest, src)` | ✅ 是 | `dest` 足够大,`src` 有 `\0` | 源无 `\0` → 无限复制 | | `strcmp(s1, s2)` | ✅ 是 | 两者都有 `\0` | 无 `\0` → 越界读 | | `qsort + strcmp` | ✅ 是 | 每个字符串块以 `\0` 结尾 | 固定长度数组缺 `\0` → 错误 | --- # 知识点(列出解答该问题需要的知识点) - **`\0` 是字符串操作的生命线** `strcpy`、`strcmp` 等函数依赖 `\0` 判断结尾,缺失将导致越界。 - **固定长度数组 ≠ 安全字符串** 即使字符填满数组,若无 `\0`,仍不能用于标准字符串函数。 - **`qsort` 中的安全比较策略** 若无法保证 `\0`,应使用手动比较或 `strncmp`,避免 `strcmp` 风险。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值