用std::string替代裸字符数组更安全,因其substr()自动处理边界和内存;substr(pos,len)中pos越界抛异常,len过大则自动截断。

用 std::string 替代裸字符数组是更安全的选择
直接操作 C 风格字符数组(如 char arr[100])截取子串,本质是手动管理内存和终止符,极易越界或漏写 '\0'。C++ 标准库的 std::string 提供了可靠的 substr(),底层自动处理长度、边界和内存。除非你明确在嵌入式环境或与 C API 交互,否则别碰裸数组截取。
如果已有字符数组需转成子串,先构造 std::string 再调用 substr():
char arr[] = "hello world"; std::string s(arr); // 全量转换 std::string sub = s.substr(6, 5); // 从索引 6 开始取 5 个字符 → "world"
substr() 的起始位置和长度参数怎么设才不越界
substr(pos, len) 中 pos 是起始索引(从 0 开始),len 是要取的字符数。关键点在于:如果 pos 超出字符串长度,会抛出 std::out_of_range;如果 len 过大,函数会自动截断到末尾,不会报错。
- 安全做法:始终检查
pos ,再调用 <code>substr() -
len可省略,此时默认取到末尾:s.substr(3)等价于s.substr(3, s.length() - 3) - 若想从倒数第 N 个字符开始截取,用
s.substr(s.length() - N),但要确保N
必须用裸字符数组时,怎么手动复制子串
真要操作 char* 或 char[],不能靠 substr(),得用 std::memcpy 或 std::strncpy,并手动补 '\0'。常见错误是忘记终止符或目标缓冲区不够大。
立即学习“C++免费学习笔记(深入)”;
示例:从 src 的第 2 位开始复制 3 个字符到 dst
char src[] = "abcdef"; char dst[4]; // 必须预留 1 字节放 '\0' std::memcpy(dst, src + 2, 3); // 复制 'c','d','e' dst[3] = '\0'; // 手动终止
- 目标数组大小至少为
len + 1 - 用
std::strncpy更保守,但它会在不足时补'\0',也可能不补——行为依赖长度比较,不如memcpy + 显式置 '\0'清晰 - 永远不要对非空终止的源数组用
strcpy或strncpy
从 C 字符串提取子串后,怎么传给需要 const char* 的函数
很多 C 接口(如 fopen、printf)要求 const char*。如果你用 std::string 截取了子串,直接调用 .c_str() 即可,它返回指向内部缓冲区的指针,内容以 '\0' 结尾。
但注意生命周期:该指针仅在原 std::string 对象有效且未被修改时有效。
std::string path = "/home/user/file.txt";
std::string filename = path.substr(path.find_last_of('/') + 1); // "file.txt"
FILE* f = std::fopen(filename.c_str(), "r"); // 安全:c_str() 在这行执行期间有效- 不要把
c_str()结果存为const char*变量长期使用 - 如果后续还会修改
filename,或其作用域即将结束,应立即使用或复制内容 - 裸字符数组本身已是
const char*,无需转换,但你要确保它已正确终止
边界检查和内存终止符是这类操作里最容易被跳过的两步,尤其在快速写原型时。宁可多写一行 if (pos < s.size()),也不要靠“应该不会超”来赌。


















