请教C++代码中嵌套for循环及第三个for循环的实现逻辑
理解这段C++代码中的嵌套循环逻辑
嘿,我来帮你拆解这段代码的逻辑,尤其是你搞不懂的嵌套循环部分~先把代码规整一下方便阅读:
string s; cin >> s; vector<int> r; // 外层的范围for循环 for (string t : {"twone", "one", "two"}) { // 内层的查找循环 for (size_t pos = 0; (pos = s.find(t, pos)) != string::npos;) { s[pos + t.length() / 2] = '?'; r.push_back(pos + t.length() / 2); } } cout << r.size() << endl; for (auto rr : r) cout << rr + 1 << " "; cout << endl;
先搞懂整体功能
这段代码的核心是在输入的字符串里,查找twone、one、two这三个特定子串,记录每个匹配子串的中间位置,同时破坏原串的匹配位置避免重复计数,最后输出找到的子串数量和这些位置(转成从1开始的索引)。
你疑惑的「第三个for循环」:外层范围for循环
你提到的第三个for循环其实是最外层的这个:
for (string t : {"twone", "one", "two"})
这是C++11之后支持的范围for循环,简单说就是依次把花括号里的每个字符串赋值给变量t,循环总共执行3次:
- 第一次:
t的值为"twone" - 第二次:
t的值为"one" - 第三次:
t的值为"two"
为啥要按这个顺序?因为twone本质是two+one的组合,如果先找one或two,会把twone拆成两个子串重复计数,先找twone就能避免这个问题。
内层的嵌套for循环:反复查找子串
内层这个循环的写法有点特殊,咱们拆成三部分解析:
for (size_t pos = 0; (pos = s.find(t, pos)) != string::npos;)
- 初始化部分:
size_t pos = 0—— 从字符串的第0位(起始位置)开始查找子串。 - 条件判断部分:
(pos = s.find(t, pos)) != string::npos- 先执行
s.find(t, pos):从当前pos的位置开始,查找子串t第一次出现的位置。 - 如果找到,就把这个位置赋值给
pos,然后判断pos是否不等于string::npos(npos是C++字符串的特殊值,表示「未找到」),条件成立就进入循环体。 - 如果没找到,
pos会被设为npos,条件不成立,循环结束。
- 先执行
- 递增部分:这里是空的!因为每次找到子串后,我们把原串的中间字符改成了
?,下次再从当前pos查找时,这个位置的子串已经被破坏,不会重复匹配,所以不需要手动移动pos。
循环体里的操作
进入循环后会执行两个关键操作:
s[pos + t.length() / 2] = '?':计算子串t的中间位置,把原串的这个位置改成?,破坏掉该子串,避免后续重复匹配。比如:twone长度是5,整数除法5/2=2,所以修改pos+2的位置,twone变成tw?ne,再也不会被匹配到。one长度是3,3/2=1,修改pos+1的位置,变成o?e。
r.push_back(pos + t.length() / 2):把这个中间位置(从0开始的索引)存入向量r,后续用来输出结果。
最后的输出逻辑
cout << r.size() << endl;:输出找到的子串总数。for (auto rr : r) cout << rr + 1 << " ";:把每个位置从0开始的索引转成从1开始的索引(编程题通常要求用1-based索引),然后依次输出。
内容的提问来源于stack exchange,提问作者McSkelly
相关产品推荐
相关产品推荐

