C/C++ 中將 std::string 轉為整數的標準方法演進與最佳實踐。
atoi / strtolstd::string s = "12345"; int val = atoi(s.c_str()); // 簡單但無錯誤檢測 long val2 = strtol(s.c_str(), nullptr, 10); // 可檢測錯誤、支援進制
缺點:atoi 非法輸入行為未定義(通常返回 0),無法區分「輸入 0」與「轉換失敗」;需手動管理 char*。
std::stoi 系列std::string s = "12345"; int val = std::stoi(s); // 拋出異常於錯誤 long val2 = std::stol(s); long long val3 = std::stoll(s); float f = std::stof(s); double d = std::stod(s);
優點:
std::string,無需 .c_str()std::invalid_argument、std::out_of_range)size_t* idx 參數獲取解析字符數base 參數,默認 10)std::string s = "123abc";
try {
size_t pos;
int val = std::stoi(s, &pos); // val=123, pos=3
// 可檢查 pos == s.size() 判斷是否完全解析
} catch (const std::invalid_argument& e) {
// 無數字開頭
} catch (const std::out_of_range& e) {
// 超出 int 範圍
}
std::from_chars(高性能、無異常)#include <charconv>
std::string s = "12345";
int val;
auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), val);
if (ec == std::errc()) {
// 成功,ptr 指向首個未解析字符
} else if (ec == std::errc::invalid_argument) {
// 格式錯誤
} else if (ec == std::errc::result_out_of_range) {
// 溢出
}
優勢:無異常開銷、無區域化依賴、可直接操作字符指針、性能極高(適合熱路徑解析)。
| 函數 | 標準 | 錯誤處理 | 性能 | 推薦場景 |
|---|---|---|---|---|
atoi | C | 無(UB) | 高 | 極簡代碼、確信輸入合法 |
strtol | C | errno/指針 | 高 | C 代碼、需檢測錯誤 |
stoi/stol/... | C++11 | 異常 | 中(異常開銷) | 通用 C++ 代碼、異常安全環境 |
from_chars | C++17 | error_code | 極高 | 高性能解析、無異常環境、嵌入式 |
std::from_charsstd::stoi 並捕獲異常atoi,除非極度確定輸入合法且不關心錯誤pos == size() 或 ptr == end)正確選擇轉換函數,能讓代碼更安全、高效、可維護。