最稳妥用std::stoi但需处理异常;std::strtol更可控,支持全匹配检查和进制指定;手写解析适用于无异常环境或定制规则;注意locale影响及双重溢出检查。

直接用 std::stoi 最稳妥,但必须处理异常;手写解析或 std::strtol 更可控,尤其面对非法输入、溢出或前导空格时。
std::stoi 适合简单场景,但不捕获细节错误
std::stoi 是最常用的转换函数,语法简洁:
std::string s = "123"; int n = std::stoi(s);
但它有三个关键限制:
- 遇到非数字字符(如
"123abc")会截断转换,返回123,不报错 - 超出
int范围时抛出std::out_of_range异常,不区分上溢/下溢 - 对空字符串、纯空格或只有符号(如
"+")直接抛std::invalid_argument
若业务要求“严格全匹配”,需额外检查转换后是否消耗了整个字符串:
立即学习“C++免费学习笔记(深入)”;
size_t pos;
int n = std::stoi(s, &pos);
if (pos != s.length()) {
// 有未解析的尾部字符,视为失败
}std::strtol 更健壮,能精确控制解析行为
std::strtol 是 C 风格函数,但 C++ 中仍推荐用于需要精细控制的场景。它返回 long,支持指定进制,并通过 endptr 指示解析终点:
const char* cstr = s.c_str(); char* endptr; long val = std::strtol(cstr, &endptr, 10);
使用时注意:
-
endptr == cstr表示一个有效数字都没识别到(如空串、纯空格) -
*endptr != '\0'表示存在尾部非法字符(如"42x") - 需手动检查
val是否在INT_MIN~INT_MAX内,再转为int,否则可能静默溢出 - 支持进制参数:
std::strtol("ff", nullptr, 16)→255
手写解析适用于嵌入式、无异常环境或自定义规则
当不能依赖 STL 异常,或需跳过前导空格、接受 '_' 分隔符、限制位数等定制逻辑时,手写更可靠。核心逻辑包括:
- 跳过开头空白(
std::isspace) - 记录符号位,移动指针
- 逐字符判断
c >= '0' && c ,累加:num = num * 10 + (c - '0') - 每步检查溢出:
if (num > (INT_MAX - digit) / 10) - 最后乘符号返回
优点是零依赖、可预测、易调试;缺点是代码量略增,需覆盖所有边界(如 "-2147483648" 这种恰好等于 INT_MIN 的情况)。
别忽略 locale 和编码问题
std::stoi 和 std::strtol 都依赖当前 C locale 的数字识别规则。默认 "C" locale 下只认 ASCII 数字 '0'–'9';若程序切换过 locale(如设为 "zh_CN.UTF-8"),某些实现可能影响解析行为——尽管实践中极少遇到非 ASCII 数字参与转换,但仍建议显式保持 C locale:
std::locale::global(std::locale("C"));或者更安全的做法:始终用 .c_str() 提供的 ASCII 字节流调用 strtol,避免 string 内容含多字节 UTF-8 数字(这本身就不符合常规整数表示)。
真正容易被忽略的是:溢出检查必须做两次——一次在 strtol 后判断范围,一次在赋值给 int 前确认值有效;而 stoi 的异常只告诉你“错了”,不告诉你错在哪一环。











