首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言字符串處理中 while 循環指針移動邏輯分析

     編輯:程式設計綜合問答

代碼片段

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`

  1. `t = f = s;` → `t` 和 `f` 都指向 `s` (地址 `s`,字符 `'*'`)。
  2. `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`)。**
  3. `t--;`
    • `t` 回退一位 → 指向 `s+6` (字符 `'*'`)。
  4. `while (*t == '*') t--;`
    • 檢查 `*t == '*'` 為真,`t` 移動:`s+6` → `s+5` (字符 `'*'`) → `s+4` (字符 `'c'`)。
    • 此時 `*t == 'c'` 不等于 `'*'`,循環結束。
    • **結果:`t` 指向 `s+4` (末尾有效字符 `'c`)。**
  5. `while (*f == '*') f++;`
    • `f` 初始指向 `s` (`'*'`)。
    • 循環:`s` (`'*'`) → `s+1` (`'*'`) → `s+2` (`'a'`)。
    • 此時 `*f == 'a'`,循環結束。
    • **結果:`f` 指向 `s+2` (首部有效字符 `'a`)。**
  6. `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 跳過頭部 *, 定位到頭部有效字符

⚠️ 關鍵缺陷 (必須修復)

  1. `gets(s)` 極度危險:無長度限制,必改 `fgets(s, sizeof(s), stdin)` + 去換行。
  2. 無邊界保護:若字符串全 `*` 或空,`t--` 和 `while` 會導致指針越界訪問 `s[-1]` 或 `s[len+1]`。
    **修正**:所有指針移動循環加條件 `t >= f` / `f <= t`。
  3. 未處理 `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 /* 全 * 或空 */;
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved