代碼片段
while (p = strstr(str1, str2)) {
strcpy(p, p + len2);
}
場景
- 原字符串
str1:"this is a dog"
- 待刪除子串
str2:"is",長度 len2 = 2
- 目標結果:
"th a dog"
逐步執行圖解
初始狀態
str1: t h i s i s a d o g \0
index: 0 1 2 3 4 5 6 7 8 9 10 11 12
↑ ↑
p p+len2 (len2=2)
第一次循環
strstr(str1, "is") 返回指向索引 2 的指針 p(第一個 'i')
p + len2 = p + 2 指向索引 4(第一個 's' 後面的空格)
strcpy(p, p + 2) 執行內存覆蓋:
複製前: p指向: i s i s a d o g \0
p+2指向: i s a d o g \0
strcpy 逐字節複製:
p[0] = (p+2)[0] → ' ' (空格)
p[1] = (p+2)[1] → 'i'
p[2] = (p+2)[2] → 's'
p[3] = (p+2)[3] → ' '
... 直到 \0
複製後 str1: t h [空格] i s a d o g \0
↑
索引2現在是空格,原"is"被覆蓋
第二次循環
strstr 從新字符串開頭搜索,找到索引 4 的 "is"(原第二個)
- 同理
strcpy 覆蓋,最終得到 "th a dog"
關鍵點總結
| 表達式 | 含義 | 作用 |
strstr(str1, str2) | 查找子串首次出現位置 | 返回指向匹配首字符的指針 |
len2 = strlen(str2) | 子串長度 | 計算跳過長度 |
p + len2 | 指針算術:向後移動 len2 個字節 | 指向子串結束後的下一字符 |
strcpy(p, p + len2) | 將源地址內容覆蓋到目標地址 | 實現「刪除」:後續內容前移覆蓋目標子串 |
內存視角理解
strcpy(dest, src) 將 src 指向的字符串(含 \0)**逐字節複製**到 dest 指向的內存區域。此處 dest = p(子串開頭),src = p + len2(子串結束後),效果是**將子串後的所有內容向前移動 len2 位**,達到刪除效果。
完整可運行代碼
#include <stdio.h>
#include <string.h>
#define SIZE 100
void deleteSubstr(char *str, const char *substr) {
size_t len = strlen(substr);
char *p;
while ((p = strstr(str, substr)) != NULL) {
strcpy(p, p + len);
}
}
int main() {
char str1[SIZE] = "this is a dog";
char str2[SIZE] = "is";
printf("原始: %s\n", str1);
deleteSubstr(str1, str2);
printf("刪除 '%s' 後: %s\n", str2, str1);
return 0;
}
輸出
原始: this is a dog
刪除 'is' 後: th a dog
注意事項
- ⚠️ **緩衝區安全**:確保
str1 有足夠空間(此處原地修改無擴容風險)
- ⚠️ **重疊複製**:
strcpy 行為未定義當源目重疊,但此處 src > dest 且向前複製,**實際安全**(C 標準庫通常向前複製處理重疊)
- 💡 **更安全**:用
memmove(p, p + len, strlen(p + len) + 1) 顯式處理重疊
- 上一篇文章: SpringMVC 靜態資源(JS/CSS)404 無法訪問:配置 <mvc:resources> 映射解決
- 下一篇文章: Java 正整數分解質因數:修復邏輯錯誤與輸出格式優化
Copyright ©
程式碼之家 All Rights Reserved