C 標準庫缺乏字串替換函數。現有開源實作多僅支援單次替換,且依賴 `strstr`、`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;
}
這個實作展示了字串處理的核心邏輯:搜尋→分割→重組,是理解高階語言 `replaceAll` 底層機制的優秀教學案例。