itoa(整數轉字符串)與 atoi(字符串轉整數)是經典面試題,雖然標準庫已提供,但手寫實現能考察對進制轉換、字符處理、邊界條件的掌握程度。
result = result * 10 + (ch - '0')int my_atoi(const char *str) {
if (!str) return 0;
// 跳過空格
while (*str == ' ') str++;
// 處理符號
int sign = 1;
if (*str == '-') { sign = -1; str++; }
else if (*str == '+') { str++; }
// 累加數值
long long result = 0; // 用長整型防溢出檢測
while (*str >= '0' && *str <= '9') {
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)(result * sign);
}
digit = n % radix,n /= radixchar *my_itoa(int n, char *str, int radix) {
if (!str || radix < 2 || radix > 36) return NULL;
static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *ptr = str;
int sign = 0;
// 處理 0
if (n == 0) {
*ptr++ = '0';
*ptr = '\0';
return str;
}
// 處理負數(僅十進制)
if (n < 0 && radix == 10) {
sign = 1;
n = -n;
}
// 反向生成數字
while (n != 0) {
*ptr++ = digits[n % radix];
n /= radix;
}
// 添加負號
if (sign) *ptr++ = '-';
*ptr = '\0';
// 反轉字符串
char *start = str, *end = ptr - 1;
while (start < end) {
char tmp = *start;
*start++ = *end;
*end-- = tmp;
}
return str;
}
int main() {
char buf[32];
// atoi 測試
printf("atoi: %d\n", my_atoi("12345")); // 12345
printf("atoi: %d\n", my_atoi("-678")); // -678
printf("atoi: %d\n", my_atoi(" +42")); // 42
printf("atoi: %d\n", my_atoi("12abc")); // 12
printf("atoi: %d\n", my_atoi("9999999999")); // INT_MAX (溢出保護)
// itoa 測試
printf("itoa: %s\n", my_itoa(12345, buf, 10)); // "12345"
printf("itoa: %s\n", my_itoa(-123, buf, 10)); // "-123"
printf("itoa: %s\n", my_itoa(255, buf, 16)); // "FF"
printf("itoa: %s\n", my_itoa(10, buf, 2)); // "1010"
printf("itoa: %s\n", my_itoa(0, buf, 10)); // "0"
return 0;
}
| 函數 | 易錯點 | 應對策略 |
|---|---|---|
| atoi | 溢出、空指針、前導空格、非數字字符 | 用 long long 累加、檢查邊界、完善輸入驗證 |
| itoa | INT_MIN 取反溢出、進制映射、緩衝區大小 | 用無符號型處理、查表法、調用者保證緩衝區 |
strtol/strtoul 等更健壯的標準庫函數itoa 非線程安全,可改為輸出參數)long long、浮點數轉換itoa(非標準、緩衝區風險)手寫 atoi/itoa 不僅是面試題,更是理解「數值與文本表示互轉」本質的最佳練習。掌握邊界處理、進制轉換、字符編碼等細節,能讓你在系統編程中更從容地應對序列化、協議解析等場景。