std::stoi转换八进制需显式指定base=8,否则按十进制解析;遇非法字符抛invalid_argument,超范围抛out_of_range;应配合pos检查完整匹配,并考虑用stoll/stoull扩展范围。

std::stoi 用 base=8 转换字符串为八进制整数
直接用 std::stoi 最简单,但必须显式指定进制,否则默认按十进制解析,"017" 会被当成十进制 17,而不是八进制 15(即十进制的 15)。
常见错误是漏传 base 参数,或误以为前缀 "0" 会自动触发八进制识别——C++ 标准库不认这个前缀(那是 C 风格字面量的语法,std::stoi 不解析前缀)。
-
std::stoi("17", nullptr, 8)→ 返回15(八进制 17 = 十进制 15) -
std::stoi("017", nullptr, 8)→ 同样返回15,开头的0被当作普通前导零,不影响结果 -
std::stoi("017")(无base)→ 返回17,纯按十进制处理
遇到非法字符时如何捕获错误
std::stoi 遇到非八进制字符(如 '8'、'9'、字母)会抛出 std::invalid_argument;超出 int 范围则抛 std::out_of_range。不加异常处理容易 crash。
- 务必用
try/catch包裹调用 - 检查是否所有字符都参与了转换:通过第二个参数
pos检查解析结束位置,比如std::stoi("17abc", &pos, 8)后pos == 2,说明只读了前两位 - 若要求“整个字符串必须严格匹配”,需额外判断
pos == str.length()
需要更大范围?用 std::stoll 或 std::stoull
std::stoi 返回 int,在多数平台是 32 位,八进制字符串如 "17777777777"(11 个 7)已超范围。这时得换更宽类型:
-
std::stoll(str, nullptr, 8)→ 返回long long,通常 64 位,支持最多约 22 位八进制数 -
std::stoull(str, nullptr, 8)→ 无符号,能多表示一位(避免负数歧义) - 注意:即使用了
stoull,输入含负号(如"-123")仍会抛invalid_argument,八进制字符串本身不应带负号;如需负值,先解析再加负号
C 风格函数 strtol 的兼容性细节
如果代码要兼容旧编译器或嵌入式环境,strtol 仍是可靠选择,但接口更底层,容易出错:
-
strtol("17", &endptr, 8)第三个参数必须是8,不能是0(0表示自动检测前缀,但八进制前缀是"0",而"017"和"17"都合法,strtol对前者识别为八进制,后者为十进制 —— 行为不一致) -
endptr必须检查:若*endptr != '\0',说明有未解析字符 - 返回值为
long,溢出时返回LONG_MAX或LONG_MIN,且设置errno = ERANGE,需手动检查
八进制转换本身不复杂,真正麻烦的是边界校验和错误路径覆盖——漏掉任意一种非法输入(空串、全空白、超长、含非法字符),线上就可能崩。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











