int my_atoi(const char *s); // 忽略前導空白、處理 +/- 號、讀取數字字元直到非數字、回傳整數 // 溢出行為:標準 atoi 未定義,strtol 可檢測
#include#include int my_atoi(const char *str) { if (!str) return 0; // 1. 跳過空白 while (isspace(*str)) str++; // 2. 處理正負號 int sign = 1; if (*str == '+' || *str == '-') { sign = (*str == '-') ? -1 : 1; str++; } // 3. 累加數字 long long result = 0; // 用長整數偵測溢出 while (isdigit(*str)) { result = result * 10 + (*str - '0'); // 溢出檢測 if (sign == 1 && result > INT_MAX) return INT_MAX; if (sign == -1 && -result < INT_MIN) return INT_MIN; str++; } return (int)(sign * result); }
| 原始碼缺陷 | 影響 | 修正 |
|---|---|---|
| 未處理前導空白 | `" 123"` 回傳 0 | 加入 `isspace` 迴圈 |
| 未檢查 `isdigit` | `"12a3"` 會把 `a` 當數字處理 | `while(isdigit(*p))` |
| 無溢出保護 | `"2147483648"` 行為未定義 | 用 `long long` 累加並比較 `INT_MAX/MIN` |
| 參數 `char s[5]` 限制長度 | 無法處理長字串 | 改為 `const char *` |
| 使用 `gets`(危險、已移除) | 緩衝區溢位風險 | 用 `fgets` 或 `scanf("%19s")` |
int main() {
printf("%d\n", my_atoi(" -123")); // -123
printf("%d\n", my_atoi("+456abc")); // 456
printf("%d\n", my_atoi("2147483647")); // INT_MAX
printf("%d\n", my_atoi("-2147483648")); // INT_MIN
printf("%d\n", my_atoi(" ")); // 0
return 0;
}
手寫 `atoi` 核心是**有限狀態機**:空白 → 符號 → 數字 → 停止。生產代碼**必須**處理空白、溢出、非數字終止。面試時寫出健壯版並解釋每個邊界條件處理,即為加分項。