std::rotate是最安全高效的标准解法,自动处理边界且时间复杂度o(n);需用k % s.size()防越界,空串和单字符也适用,无需额外判断。

用 std::rotate 最安全高效
直接调用 std::rotate 是 C++ 标准库提供的标准解法,无需手动管理索引越界或内存,且对任意迭代器类型(包括 std::string)通用。
它把区间分为两段,把前段移到后段之后——这正好对应循环左移:把前 n 个字符“切下来”贴到末尾。
示例:
#include <string> #include <algorithm> #include <iostream> std::string s = "abcdef"; int k = 2; std::rotate(s.begin(), s.begin() + k % s.size(), s.end()); // 结果: "cdefab" </iostream></algorithm></string>
-
k % s.size()必须做,否则k > s.size()时会越界 - 空字符串或
s.size() == 1时,std::rotate行为定义良好,无需额外判断 - 时间复杂度 O(n),内部是三次反转,常数因子小,比手写拼接更省内存
手写拼接要注意 substr 的参数顺序
如果不用算法库,常见做法是拆成两段再拼:后半段 + 前半段。但 std::string::substr 第二个参数是长度,不是结束位置,容易写错。
错误写法:s.substr(k, s.size()) —— 这会导致越界或截断;正确是:
int n = s.size(); int k_mod = k % n; if (n == 0) return s; s = s.substr(k_mod) + s.substr(0, k_mod);
-
s.substr(pos)从pos到结尾;s.substr(0, k_mod)取前k_mod个字符 - 必须先算
k_mod,否则k > n时substr(k)抛std::out_of_range - 该方法产生两次临时字符串拷贝,对长字符串有性能开销
原地反转三步法避免额外空间
想省掉拼接的内存分配?可以用三次反转实现真正原地操作,原理是:XY → YX 等价于 XY → X'Y' → (X'Y')' = YX。
对左移 k 位:先反转 [0, k),再反转 [k, n),最后反转整个串。
int n = s.size(); if (n == 0) return; k = k % n; std::reverse(s.begin(), s.begin() + k); std::reverse(s.begin() + k, s.end()); std::reverse(s.begin(), s.end());
- 注意三处边界:前两步是半开区间,第三步是全串
- 和
std::rotate底层策略一致,但显式写出更利于理解或调试 - 若字符串很大且内存敏感(如嵌入式场景),这是比拼接更优的选择
遇到 std::out_of_range 优先检查模运算和空串
几乎所有崩溃都来自没处理好边界:空串、k 超长、或忘记取模。
典型报错:basic_string::substr: __pos (which is 5) > this->size() (which is 3)。
- 只要用了
substr或直接下标访问,就必须在之前做if (s.empty())和k %= s.size() -
std::rotate和std::reverse在合法迭代器范围内不会抛异常,但传入非法迭代器(如s.begin() + k越界)是未定义行为,编译器不一定报错 - 建议所有函数入口加一句:
if (s.empty()) return;,比到处判更稳妥
std::rotate 就够了;真要抠性能或教学演示,才展开三步反转。最容易被忽略的是:哪怕只调一次 substr,也得先做模运算——不然后续所有逻辑都建立在错误前提上。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











