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

C 語言字串替換函數完整實作:支援全域替換、無庫函數依賴

     編輯:關於C

需求背景

C 標準庫缺乏字串替換函數。現有開源實作多僅支援單次替換,且依賴 `strstr`、`memcpy` 等庫函數。本實作目標:

  • 支援全域替換(所有出現位置)
  • 完全自給自足:自行實作 `my_strstr`、`my_memcpy`
  • 記憶體安全:呼叫端提供足夠大的輸出緩衝區

核心函數架構


// 1. 子字串搜尋:返回首次出現位址,未找到返回 NULL
char* my_strstr(char* haystack, char* needle);

// 2. 記憶體複製:標準 memcpy 實作
void* my_memcpy(void* dest, const void* src, size_t n);

// 3. 字串替換主函數
// 返回替換次數,結果寫入 result 緩衝區
int str_replace(char* result, char* source, char* search, char* replace);

完整實作程式碼

#include 
#include 

// 子字串搜尋 (類 strstr)
char* my_strstr(char* ps, char* pd) {
    char* pt = pd;
    int c = 0;
    while (*ps != '\0') {
        if (*ps == *pd) {
            while (*ps == *pd && *pd != '\0') {
                ps++; pd++; c++;
            }
        } else {
            ps++;
        }
        if (*pd == '\0') return (ps - c);
        c = 0;
        pd = pt;
    }
    return NULL;
}

// 記憶體複製 (類 memcpy)
void* my_memcpy(void* dest, const void* src, size_t count) {
    char* tmp = (char*)dest;
    const char* s = (const char*)src;
    while (count--) *tmp++ = *s++;
    return dest;
}

// 字串全域替換
int str_replace(char* result, char* source, char* search, char* replace) {
    int count = 0;
    int search_len = strlen(search);
    int replace_len = strlen(replace);
    char* psource = source;
    char* presult = result;
    char* p1;

    do {
        p1 = my_strstr(psource, search);
        if (!p1) {
            strcpy(presult, psource);  // 複製剩餘部分
            return count;
        }
        count++;
        
        // 複製「上一替換點到本替換點」的中間段
        int n = p1 - psource;
        my_memcpy(presult, psource, n);
        
        // 複製替換字串
        my_memcpy(presult + n, replace, replace_len);
        
        // 移動指標
        psource = p1 + search_len;
        presult = presult + n + replace_len;
    } while (p1);

    return count;
}

測試程式與輸出

#define MAX 200
int main() {
    char s[MAX] = {0}, s1[MAX] = {0}, s2[MAX] = {0}, result[2000] = {0};
    
    puts("請輸入原字串:"); scanf("%s", s);
    puts("請輸入搜尋字串:"); scanf("%s", s1);
    puts("請輸入替換字串:"); scanf("%s", s2);
    
    int n = str_replace(result, s, s1, s2);
    printf("替換 %d 個子字串\n", n);
    printf("結果: %s\n", result);
    return 0;
}
輸入:
原字串: 123123123123
搜尋字串: 23
替換字串: abcdefg

輸出:
替換 4 個子字串
結果: 1abcdefg1abcdefg1abcdefg1abcdefg

演算法流程圖解

source:  1 2 3 1 2 3 1 2 3 1 2 3
search:       "23"
replace: "abcdefg" (len=7)

迴圈 1: 找到位置 1
  複製 source[0..0] → "1"
  複製 replace      → "abcdefg"
  psource 指向 3
  
迴圈 2: 找到位置 3 (相對新 psource)
  複製 "1" → "1"
  複製 "abcdefg"
  ...

結果: 1 abcdefg 1 abcdefg 1 abcdefg 1 abcdefg

關鍵設計決策

決策點選擇理由
搜尋演算法朴素 O(nm)教學清晰,短字串足夠;長字串可換 KMP/BM
記憶體管理呼叫端分配 result避免函數內 malloc/free,控制權在上層
重疊替換不支援 (搜尋指標跳過替換區)標準行為;如 "aaa" 替 "aa"→"b" 結果 "ba" 非 "bb"
空字串處理search 為空會無限迴圈實務需加入 `if (!*search) return 0;` 防護

改良版:安全性與效能增強

int str_replace_safe(char* result, size_t result_size, 
                     const char* source, const char* search, const char* replace) {
    if (!source || !search || !replace || !*search) return 0;
    if (!result || result_size == 0) return -1;
    
    size_t search_len = strlen(search);
    size_t replace_len = strlen(replace);
    const char* ps = source;
    char* pr = result;
    char* end = result + result_size - 1;  // 保留結尾 \0 空間
    int count = 0;
    
    while (*ps && pr < end) {
        const char* found = my_strstr((char*)ps, (char*)search);
        if (!found) break;
        
        // 複製中間段
        size_t n = found - ps;
        if (pr + n >= end) return -1;  // 緩衝區不足
        my_memcpy(pr, ps, n);
        pr += n;
        
        // 複製替換串
        if (pr + replace_len >= end) return -1;
        my_memcpy(pr, replace, replace_len);
        pr += replace_len;
        
        ps = found + search_len;
        count++;
    }
    
    // 複製尾部
    size_t tail_len = strlen(ps);
    if (pr + tail_len >= end) return -1;
    strcpy(pr, ps);
    
    return count;
}

效能考量

  • 時間複雜度:O(n × m) 搜尋 + O(n) 複製,n=源字串長,m=搜尋字串長
  • 大量替換場景:考慮 KMP (O(n+m)) 或 Boyer-Moore 搜尋
  • 記憶體:結果長度 ≤ 原長 + 替換次數 × (替換長 - 搜尋長)

這個實作展示了字串處理的核心邏輯:搜尋→分割→重組,是理解高階語言 `replaceAll` 底層機制的優秀教學案例。

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