標準庫 <stdlib.h> 提供 atoi、itoa (非標準但常見)、atof 等轉換函式。理解其底層實作邏輯,不僅能應付面試手寫題,更能深入掌握字串解析、數值累積、邊界處理等核心程式設計技巧。本文提供三個函式的完整實作碼與逐行解析。
atoiint atoi(char s[]) {
int i, n, sign;
// 1. 跳過前導空白
for (i = 0; isspace(s[i]); i++);
// 2. 處理正負號
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-') i++;
// 3. 累積數值 (ASCII '0' = 48)
for (n = 0; isdigit(s[i]); i++)
n = n * 10 + (s[i] - '0');
return sign * n;
}
isspace 處理空白、Tab、換行等。s[i] - '0' 將字元數字轉為整數值 (如 '5' - '0' = 5)。n = n * 10 + digit 是經典的「左移累積」演算法。itoa
void reverse(char s[]) {
int c, i, j;
for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
c = s[i]; s[i] = s[j]; s[j] = c;
}
}
void itoa(int n, char s[]) {
int i, sign;
// 1. 記錄正負號,轉為正數處理
if ((sign = n) < 0) n = -n;
// 2. 從個位數開始產生字元 (逆序)
i = 0;
do {
s[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
// 3. 補上負號
if (sign < 0) s[i++] = '-';
s[i] = '\0';
// 4. 反轉字串得到正確順序
reverse(s);
}
do-while 確保 n=0 也能產生 "0"。reverse() 一次完成,避免複雜的索引計算。reverse 採雙指標對調,空間 O(1),時間 O(n)。atof
double atof(char s[]) {
double val, power;
int i, sign;
// 1. 跳過空白
for (i = 0; isspace(s[i]); i++);
// 2. 正負號
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-') i++;
// 3. 整數部分累積
for (val = 0.0; isdigit(s[i]); i++)
val = val * 10.0 + (s[i] - '0');
// 4. 小數點處理
if (s[i] == '.') i++;
// 5. 小數部分累積,同時計算 10 的冪次
for (power = 1.0; isdigit(s[i]); i++) {
val = val * 10.0 + (s[i] - '0');
power *= 10.0;
}
return sign * val / power;
}
輸入: " -123.45 " 步驟1: i 跳過空白 → 指向 '-' 步驟2: sign = -1, i 指向 '1' 步驟3: val 累積 1→12→123 步驟4: 遇到 '.', i++ 步驟5: val 累積 1234→12345, power 累積 10→100 結果: -1 * 12345 / 100 = -123.45
| 函式 | 標準庫 | 手寫版優缺點 | 生產環境建議 |
|---|---|---|---|
| atoi | stdlib.h | 簡單但無錯誤處理 | 用 strtol (可檢測錯誤、支援進制) |
| itoa | 非標準 | 邏輯清晰、教學價值高 | 用 snprintf (安全、標準) |
| atof | stdlib.h | 不支援科學記號、無錯誤處理 | 用 strtod (完整、健壯) |
1.23e-4 科學記號的 atof。strtol 完整功能:進制自動偵測 (0x/0)、endptr 回傳解析位置、errno 溢位標記。INT_MIN 絕對值溢位問題 ( -INT_MIN 會溢位 )。核心收穫:型別轉換的本質是 字元編碼與數值系統的映射。掌握「累積乘 10 + 當前位」與「取模 10 取當前位」這對對偶操作,即掌握了進制轉換的通用鑰匙。