C语言字符串比较必须使用标准库函数(如strcmpstrncmp),不可用==直接比较(因比较的是地址而非内容);strcmp返回整数(<0、0、>0表示大小关系),strncmp可指定比较长度,比较时需严格判断返回值正负零而非具体数值。

在C语言中,字符串比较是一项基础但重要的操作。由于C语言没有将字符串作为独立的数据类型,而是将其视为字符数组,因此不能直接使用==比较两个字符串的内容,必须使用专门的字符串比较函数。

为什么不能直接用==比较字符串?

char s1[] = "hello";
char s2[] = "hello";
printf("%d", s1 == s2); // 输出0,因为比较的是地址,不是内容

上面的代码比较的是字符串的地址,而不是字符串的内容。正确做法是使用strcmp函数逐字符比较内容。

主要字符串比较函数

1. strcmp - 完整字符串比较

  • 头文件#include <string.h>
  • 函数原型int strcmp(const char *s1, const char *s2);
  • 返回值
    • 0:两个字符串完全相同
    • <0:s1按字典序小于s2
    • >0:s1按字典序大于s2
  • 比较规则:从第一个字符开始,逐个比较ASCII码值,直到遇到不同字符或\0

示例代码

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

int main() {
    char str1[] = "apple";
    char str2[] = "banana";
    
    int result = strcmp(str1, str2);
    
    if (result < 0) {
        printf("\"%s\" is less than \"%s\"\n", str1, str2);
    } else if (result > 0) {
        printf("\"%s\" is greater than \"%s\"\n", str1, str2);
    } else {
        printf("\"%s\" is equal to \"%s\"\n", str1, str2);
    }
    
    return 0;
}

2. strncmp - 部分字符串比较

  • 头文件#include <string.h>
  • 函数原型int strncmp(const char *s1, const char *s2, size_t n);
  • 参数
    • n:要比较的最大字符数
  • 返回值:与strcmp相同
  • 用途:比较字符串的前n个字符,适用于需要部分匹配的情况

示例代码

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

int main() {
    char str1[] = "hello world";
    char str2[] = "hello there";
    
    int result = strncmp(str1, str2, 5);
    
    if (result == 0) {
        printf("前5个字符相同\n");
    } else {
        printf("前5个字符不同\n");
    }
    
    return 0;
}

3. strcasecmp - 不区分大小写的比较

  • 头文件#include <strings.h>
  • 函数原型int strcasecmp(const char *s1, const char *s2);
  • 特点:忽略大小写进行比较,非标准C库函数,是POSIX扩展
  • 返回值:与strcmp相同

示例代码

#include <stdio.h>
#include <strings.h>

int main() {
    char str1[] = "Hello";
    char str2[] = "hello";
    
    int result = strcasecmp(str1, str2);
    
    if (result == 0) {
        printf("字符串在忽略大小写的情况下相等\n");
    } else {
        printf("字符串在忽略大小写的情况下不相等\n");
    }
    
    return 0;
}

常见误区

❌ 误区1:返回值一定是-1、0、1

// 错误!返回值可能不是-1、0、1
if (strcmp("abc", "abd") == -1) { ... }

正确用法:只判断正负零

if (strcmp(str1, str2) < 0) { /* str1 < str2 */ }

❌ 误区2:用==比较字符串

// 错误!比较的是地址
if (str1 == str2) { ... }

// 正确!
if (strcmp(str1, str2) == 0) { ... }

最佳实践

  1. 处理NULL指针:在使用字符串比较函数前,应确保指针不为NULL
  2. 避免未终止字符串:确保字符串以\0结尾,否则可能导致内存越界
  3. 使用strncmp处理固定长度数据:在比较固定长度数据时优先使用strncmp
  4. 处理中文等多字节字符:标准的strcmp函数对中文等多字节字符比较可能不适用,需要使用专用的比较函数

实现strcmp的自定义版本

#include <stdio.h>
#include <assert.h>

int my_strcmp(const char *str1, const char *str2) {
    assert(str1 && str2); // 空指针检查
    
    while (*str1 == *str2) {
        if (*str1 == '\0') { // 同时到结尾,说明相等
            return 0;
        }
        str1++;
        str2++;
    }
    
    // 使用unsigned char避免符号扩展问题
    return (unsigned char)*str1 - (unsigned char)*str2;
}

int main() {
    char str1[] = "abcd";
    char str2[] = "asbcd";
    
    int ret = my_strcmp(str1, str2);
    printf("my_strcmp(str1, str2) = %d\n", ret); // 输出负数
    
    return 0;
}

总结

  • strcmp用于完整字符串比较
  • strncmp用于比较前n个字符
  • strcasecmp用于不区分大小写的比较
  • 比较字符串时,永远不要==比较字符串地址
  • 比较结果时,只判断正负零,不要假设具体返回值

这些函数是C语言中处理字符串比较的基础,正确理解和使用它们能避免很多常见错误。