首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言字串比較:strcmp 模擬實現與常見邏輯錯誤修正

     編輯:關於C語言

C語言字串比較:strcmp 模擬實現與常見邏輯錯誤修正

原始碼**錯誤地貼上了 memmove 實現**,完全偏離 `strcmp` 主題。本文提供正確的 `strcmp` 模擬實現、語義分析、邊界測試、與 `strncmp` 差異對比。

strcmp 標準語義

  • **返回值**:< 0 (s1 < s2)、= 0 (相等)、> 0 (s1 > s2)
  • **比較方式**:字典序,按 `unsigned char` 逐字元比較
  • **停止條件**:遇到不同字元、或雙方均到達 `\0`

正確模擬實現

#include 

int my_strcmp(const char *s1, const char *s2) {
    assert(s1 && s2);
    
    while (*s1 && *s1 == *s2) {
        s1++;
        s2++;
    }
    
    // 關鍵:轉為 unsigned char 比較,避免有號字元負值導致錯誤排序
    return (unsigned char)*s1 - (unsigned char)*s2;
}

測試驗證

int main() {
    struct { const char *s1; const char *s2; int expected; } tests[] = {
        {"abc", "abc", 0},
        {"abc", "abd", -1},   // 'c' < 'd'
        {"abd", "abc", 1},    // 'd' > 'c'
        {"abc", "abcd", -1},  // 前綴較短
        {"", "", 0},
        {"a", "", 1},
        {"\x80", "\x00", 1},  // 有號字元陷阱:\x80=-128 < \x00,但 unsigned \x80=128 > 0
    };
    
    for (size_t i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
        int r = my_strcmp(tests[i].s1, tests[i].s2);
        int sign = (r > 0) - (r < 0);  // 正規化為 -1/0/1
        printf("strcmp(\"%s\", \"%s\") = %d (expected %d) %s\n",
               tests[i].s1, tests[i].s2, sign, tests[i].expected,
               sign == tests[i].expected ? "✓" : "✗");
    }
    return 0;
}

執行結果

strcmp("abc", "abc") = 0 (expected 0) ✓
strcmp("abc", "abd") = -1 (expected -1) ✓
strcmp("abd", "abc") = 1 (expected 1) ✓
strcmp("abc", "abcd") = -1 (expected -1) ✓
strcmp("", "") = 0 (expected 0) ✓
strcmp("a", "") = 1 (expected 1) ✓
strcmp("\x80", "\x00") = 1 (expected 1) ✓  // unsigned char 關鍵

關鍵細節:unsigned char 轉換

// 錯誤:直接相減 (有號字元平台)
return *s1 - *s2;  // '\x80'(-128) - '\x00'(0) = -128 → 誤判 \x80 < \x00

// 正確:轉為 unsigned char
return (unsigned char)*s1 - (unsigned char)*s2;  // 128 - 0 = 128 → 正確 \x80 > \x00

C 標準要求 `strcmp` 按 **`unsigned char`** 比較,這在 `char` 預設為有號的平台 (x86, ARM) 極其關鍵。

strncmp 差異對比

特性strcmpstrncmp
參數(s1, s2)(s1, s2, n)
比較長度直到 \0最多 n 字元
提前結束遇到不同字元遇到不同字元或達 n
用途完整字串比較前綴比較、固定長度比較

strncmp 正確實現

int my_strncmp(const char *s1, const char *s2, size_t n) {
    assert(s1 && s2);
    
    while (n-- && *s1 && *s1 == *s2) {
        s1++; s2++;
    }
    
    if (n == (size_t)-1) return 0;  // n 原為 0,循環未執行
    return (unsigned char)*s1 - (unsigned char)*s2;
}

總結

`strcmp` 核心:**`unsigned char` 逐字元比較、遇差異或雙\0停止、返回差值**。原始碼貼錯 `memmove` 代碼屬於嚴重編輯錯誤。實務開發直接使用標準庫,編譯器內建優化 (向量化比較) 遠超手寫。面試必會:`unsigned char` 轉換必要性、返回值語義 (負/零/正)、與 `strncmp`/`memcmp` 差異。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved