代碼片段
char s[81], *t, *f;
gets(s);
t = f = s;
while (*t) t++;
t--;
while (*t == '*') t--;
while (*f == '*') f++;
fun(s, f, t);
逐步執行圖解
假設輸入:`s = "**abc**"` (內存:`'*' '*' 'a' 'b' 'c' '*' '*' '\\0'`)
地址: `s s+1 s+2 s+3 s+4 s+5 s+6 s+7`
- `t = f = s;` → `t` 和 `f` 都指向 `s` (地址 `s`,字符 `'*'`)。
- `while (*t) t++;`
- 循環檢查 `*t` 是否非 0。
- `t` 依次移動:`s` → `s+1` → `s+2` → `s+3` → `s+4` → `s+5` → `s+6` → `s+7` (此處 `*t == '\\0'`,值為 0,循環結束)。
- **結果:`t` 指向 `s+7` (結束符 `\\0`)。**
- `t--;`
- `t` 回退一位 → 指向 `s+6` (字符 `'*'`)。
- `while (*t == '*') t--;`
- 檢查 `*t == '*'` 為真,`t` 移動:`s+6` → `s+5` (字符 `'*'`) → `s+4` (字符 `'c'`)。
- 此時 `*t == 'c'` 不等于 `'*'`,循環結束。
- **結果:`t` 指向 `s+4` (末尾有效字符 `'c`)。**
- `while (*f == '*') f++;`
- `f` 初始指向 `s` (`'*'`)。
- 循環:`s` (`'*'`) → `s+1` (`'*'`) → `s+2` (`'a'`)。
- 此時 `*f == 'a'`,循環結束。
- **結果:`f` 指向 `s+2` (首部有效字符 `'a`)。**
- `fun(s, f, t);`
- 傳遞原數組首地址 `s`、有效起始指針 `f` (指向 `'a`)、有效結束指針 `t` (指向 `'c`)。
- `fun` 可處理 `f` 到 `t` 之間的子串 `"abc"`。
核心邏輯總結
// 1. t 走到字符串末尾 (\0)
while (*t) t++;
t--; // 2. t 指向最後一個字符
while (*t == '*') t--; // 3. t 跳過尾部 *, 定位到尾部有效字符
while (*f == '*') f++; // 4. f 跳過頭部 *, 定位到頭部有效字符
⚠️ 關鍵缺陷 (必須修復)
- `gets(s)` 極度危險:無長度限制,必改 `fgets(s, sizeof(s), stdin)` + 去換行。
- 無邊界保護:若字符串全 `*` 或空,`t--` 和 `while` 會導致指針越界訪問 `s[-1]` 或 `s[len+1]`。
**修正**:所有指針移動循環加條件 `t >= f` / `f <= t`。
- 未處理 `f > t` 情況:全 `*` 時 `f` 會超過 `t`,調用 `fun` 需判斷 `if (f <= t)`。
健壯版本
fgets(s, sizeof(s), stdin);
s[strcspn(s, "\n")] = 0;
char *t = s, *f = s;
while (*t) t++;
if (t > s) t--; // 非空串回退
while (t >= f && *t == '*') t--; // 含下界檢查
while (f <= t && *f == '*') f++; // 含上界檢查
if (f <= t) fun(s, f, t); // 有有效區間才調用
else /* 全 * 或空 */;