C 標準庫提供多套字符串轉數字函數,功能從簡單到強大。本文系統對比 atoi/atol/atof 與 strtol/strtoul/strtod 族,重點講解錯誤檢測、溢出處理、進制支持。
| 函數 | 返回類型 | 頭文件 | 示例 |
|---|---|---|---|
atoi | int | stdlib.h | atoi("123") → 123 |
atol | long | stdlib.h | atol("1234567890") |
atof | double | stdlib.h | atof("3.14") → 3.14 |
⚠️ 缺陷:無法區分「轉換結果為 0」與「轉換失敗」,溢出行為未定義。
double strtod(const char* nptr, char** endptr);
long strtol(const char* nptr, char** endptr, int base);
unsigned long strtoul(const char* nptr, char** endptr, int base);
endptr:輸出參數,指向第一個未被轉換的字符base:進制(2-36),0 表示自動檢測(0x 十六進制、0 八進制、其他十進制)errno = ERANGE,返回 LONG_MAX/MIN 或 ULONG_MAX
char* str = "1234567891011121314151617181920"; // 超出 unsigned long
unsigned long num;
char* leftover;
errno = 0;
num = strtoul(str, &leftover, 10);
if (errno == ERANGE) {
printf("溢出!最大值:%lu\n", ULONG_MAX);
printf("未轉換部分:%s\n", leftover);
}
strtol("0xfea593ee", NULL, 0); // 自動識別 16 進制 → 4271436782
strtol("fea593ee", NULL, 16); // 顯式 16 進制
strtoul("fea593ee", NULL, 16); // 無符號,避免符號位誤判
💡 strtol 處理高位為 1 的 16 進制數會當作負數(符號擴展),16 進制轉換首選 strtoul。
long safe_strtol(const char* s, int base, bool* ok) {
errno = 0;
char* end;
long val = strtol(s, &end, base);
*ok = (errno == 0 && end != s && *end == '\0');
return val;
}
std::stoi("123"); // 拋出異常可捕獲
std::stol("123", nullptr, 16);
std::stod("3.14");
std::from_chars(ptr, ptr+len, val); // C++17 無異常、高性能
atoi 族strtol/strtoul/strtod:支持錯誤檢測、溢出處理、進制自動識別、殘餘字符定位strtoulstd::from_chars(高性能、無異常、無 locale 開銷)