C++ substr怎么用 C++截取子字符串常用方法演示【库函数】

8次阅读

substr是std::String成员函数,有两个重载:无参版取0到末尾,二参版substr(pos,len)中pos为起始下标、len为字符数(非结束下标);pos越界抛out_of_range异常,pos等于长度时返回空串,len超长则自动截断。

C++ substr怎么用 C++截取子字符串常用方法演示【库函数】

substr 函数的基本用法和参数含义

substrstd::string 的成员函数,不是全局库函数,调用前必须确保对象std::string 类型。它有两个重载形式:substr()(无参,默认取从 0 到末尾)和 substr(size_t pos, size_t len)(常用)。第一个参数 pos 是起始下标(从 0 开始),第二个参数 len 是要截取的字符个数,**不是结束下标**。

常见错误:传入 pos 超出字符串长度(比如 s.substr(10, 3)s.Length() == 5),此时会抛出 std::out_of_range 异常。c++11 起不接受负数索引,也不支持 python 风格的倒序写法(如 -2)。

  • pos == str.length(),返回空字符串 ""(合法)
  • len 超出剩余长度,substr 自动截断到末尾,不会报错
  • 避免裸写 s.substr(i, j-i) 而不检查 i 和 i

替代方案:用迭代器 + string 构造更灵活地截取

当需要基于位置计算复杂、或想复用已有迭代器时,直接构造 std::stringsubstr 更安全。例如从第 2 个字符开始取 4 个:

std::string s = "hello world"; std::string sub(s.begin() + 2, s.begin() + 6); // "llo "

这种方式绕过了 substrpos 范围的严格检查,但要求两个迭代器都在合法范围内(否则行为未定义)。适用于已知有效区间、或配合 find/find_first_of 等返回迭代器的算法使用。

立即学习C++免费学习笔记(深入)”;

  • substr 少一次边界检查开销(但通常可忽略)
  • 不能用于 std::string_view 直接构造(需先转为 std::string 或用其 own substr
  • 注意:s.begin() + n 对短字符串高效,对 std::list<:string> 这类不支持随机访问的容器不适用

处理中文或 UTF-8 字符串时 substr 会出问题吗

会。substr 按字节操作,不识别 UTF-8 编码单元。例如一个汉字通常占 3 字节,若在中间截断,结果是非法 UTF-8 字节序列,后续输出或转换可能乱码或失败。

没有标准库内置的 UTF-8 安全子串函数。实际项目中应:

  • 优先用 std::string_view + 第三方库(如 ICU、utf8cpp)做 Unicode-aware 截取
  • 若确定输入只含 ASCII,substr 安全可用
  • 避免用 substr 做“取前 N 个字符”逻辑,改用循环 + utf8::next 类函数计数码点

std::string_view::substr 性能优势与使用限制

C++17 引入的 std::string_view 也有 substr 成员函数,它不分配内存,只记录起始指针和长度,因此零拷贝、极快。但它要求原始字符串生命周期长于 string_view 对象本身。

const char* raw = "temp data"; std::string_view sv(raw); auto part = sv.substr(2, 4); // 安全:raw 仍有效 // 但下面这行危险: // auto bad = std::string("hello").substr(1, 3); // 错!临时 string 析构后 view 悬空
  • string_view::substr 参数语义和 string::substr 完全一致
  • 不能隐式转成 std::string,需要显式调用 std::string(view) 构造
  • 在函数参数中优先用 string_view 接收,内部再按需调用 substr,避免无谓拷贝

C++ 的 substr 看似简单,真正容易出错的是边界条件、UTF-8 处理和生命周期管理——尤其混用 string_view 时,悬空指针比越界访问更难调试。

text=ZqhQzanResources