substr第一个参数是起始位置(从0开始),第二个参数是截取长度而非结束下标;pos超界抛out_of_range,len超剩余长度则自动截断到末尾。

substr 的两个参数怎么填
substr 是 std::string 的成员函数,签名是 string substr(size_t pos = 0, size_t len = npos) const。第一个参数 pos 是起始位置(从 0 开始),第二个参数 len 是要截取的长度,不是结束下标。
常见错误是把 len 当成“到第几个字符为止”,比如想取索引 2~5(共 4 个字符),写成 s.substr(2, 5) —— 这实际会取 5 个字符,可能越界或结果不对。
- 安全写法:明确长度,
s.substr(2, 4) - 如果只传一个参数,如
s.substr(3),表示从索引 3 到末尾 -
pos超出字符串长度(但 ≤s.length())时抛std::out_of_range;等于s.length()是合法的,返回空串 -
len超过剩余长度时,自动截断到末尾,不会报错
处理中文或 UTF-8 字符串时为什么 substr 会乱码
substr 按字节操作,不识别 UTF-8 编码边界。一个中文字符占 3 字节,若 pos 或 len 落在某个汉字中间,截出来就是非法 UTF-8 序列,显示为 或解析失败。
- 纯 ASCII 字符串(英文、数字、基本符号)可放心用
substr - 含中文、emoji 等场景,必须先转成 Unicode 码点再切分,例如用
std::wstring+std::mbstowcs,或引入 ICU / utf8cpp 库 - 简单规避:确保
pos和每个截断点都在字节边界上(比如只在空格、换行、ASCII 标点后切),但这不通用
替代方案:C++17 以后有没有更安全的切片方式
标准库没有内置的 UTF-aware 子串函数,但 C++17 引入了 std::string_view,它和 substr 行为一致(仍是字节级),只是开销更低——不拷贝数据,只持引用和长度。
立即学习“C++免费学习笔记(深入)”;
- 性能敏感且确定是 ASCII 场景,优先用
string_view:string_view sv = s.substr(5, 3); - 注意:
string_view不拥有数据,原string生命周期必须长于它的使用期 - 真需要按字符切?只能手动遍历 UTF-8 字节序列,或依赖第三方,比如:
utf8::substr(s, start_char_index, char_count)(来自 utf8cpp)
常见报错 std::out_of_range 怎么快速定位
错误信息通常是:basic_string::substr: __pos (which is 12) > this->size() (which is 10)。说明你传的 pos 已经超出字符串当前长度。
- 检查是否忘了调用
.length()或.size()就直接算下标,比如s[i+5]前没判断i+5 - 用
at()替代[]可提前暴露越界访问,但它不解决substr参数问题 - 调试小技巧:在调用前加断言,
assert(pos ,或用三元表达式兜底:s.substr(pos > s.size() ? 0 : pos, len)
pos 和 len 的语义、UTF-8 边界、异常触发条件这三点,任一疏忽都会导致线上静默错误或崩溃。尤其服务端处理用户输入时,别假设输入全是英文。










