C 標準庫缺乏字串替換函數,開源實現多僅支援單次替換。本文實現一個全域替換、零標準庫依賴(自製 my_strstr、memcpy)、記憶體安全的 str_replace 函數。
my_strstr/* 回傳:找到→子字串在源字串中的位址;未找到→NULL */
char *my_strstr(char *haystack, char *needle) {
if (!haystack || !needle) return NULL;
if (*needle == '\0') return haystack; // 空字串匹配開頭
char *h = haystack;
while (*h) {
char *h1 = h, *n = needle;
while (*h1 && *n && *h1 == *n) {
h1++; n++;
}
if (*n == '\0') return h; // 完全匹配
h++;
}
return NULL;
}
my_memcpyvoid *my_memcpy(void *dest, const void *src, size_t n) {
char *d = (char *)dest;
const char *s = (const char *)src;
while (n--) *d++ = *s++;
return dest;
}
str_replace/* 參數:
result - 輸出緩衝區(呼叫者保證足夠大)
source - 原始字串
search - 要被替換的子字串
replace - 替換字串
回傳:替換次數
*/
int str_replace(char *result, const char *source,
const char *search, const char *replace) {
if (!result || !source || !search || !replace) return -1;
if (*search == '\0') return -1; // 避免無限迴圈
size_t search_len = 0, replace_len = 0;
const char *p;
for (p = search; *p; p++) search_len++;
for (p = replace; *p; p++) replace_len++;
int count = 0;
const char *src_pos = source;
char *dst_pos = result;
while (1) {
char *found = my_strstr((char *)src_pos, (char *)search);
if (!found) break; // 無更多匹配
/* 1. 複製匹配點前的內容 */
size_t prefix_len = found - src_pos;
my_memcpy(dst_pos, src_pos, prefix_len);
dst_pos += prefix_len;
/* 2. 複製替換字串 */
my_memcpy(dst_pos, replace, replace_len);
dst_pos += replace_len;
/* 3. 移動源位置跳過被替換部分 */
src_pos = found + search_len;
count++;
}
/* 4. 複製剩餘尾部 */
while (*src_pos) *dst_pos++ = *src_pos++;
*dst_pos = '\0';
return count;
}
#include <stdio.h>
#define MAX 2000
int main() {
char source[MAX] = "123123123123";
char search[] = "23";
char replace[] = "abcdefg";
char result[MAX] = {0};
int n = str_replace(result, source, search, replace);
printf("原始: %s\n", source);
printf("搜尋: %s\n", search);
printf("替換: %s\n", replace);
printf("次數: %d\n", n);
printf("結果: %s\n", result);
// 預期: 1abcdefg1abcdefg1abcdefg1abcdefg
return 0;
}
原始: 123123123123 搜尋: 23 替換: abcdefg 次數: 4 結果: 1abcdefg1abcdefg1abcdefg1abcdefg
| 決策點 | 選擇 | 理由 |
|---|---|---|
| 零庫依賴 | 自製 strstr/memcpy | 嵌入式/核心環境適用;教學價值高 |
| 輸出緩衝區由呼叫者分配 | 靜態陣列/動態分配皆可 | 避免函數內 malloc,呼叫者控制生命週期 |
| 不修改原字串 | const source | 符合函數式風格,線程安全 |
| 空搜尋字串保護 | 直接回傳錯誤 | 避免無限迴圈(每個位置都匹配空字串) |
當前實現不支援重疊匹配(如 "aaa" 替換 "aa" → 僅替換一次)。若需重疊,查找後 src_pos = found + 1 而非 + search_len。正則表達式建議整合 PCRE 或 RE2 庫。