C++控制台行反转程序触发SIGINT中断的原因及修正方案
问题分析与修复:VSCode+g++环境下vector逆序遍历触发SIGINT中断
我来帮你拆解下这个问题的根源,以及对应的修复方案——你的代码里有几个关键的细节错误,最终导致了程序停滞和SIGINT中断:
一、导致问题的核心原因
1. string::substr 参数用错了
你写的 strLines.substr(oldIndex, newIndex+1) 是错误的!C++里substr的第二个参数是要截取的长度,不是结束位置的索引。这会导致每次截取的字符串长度远超预期,甚至越界读取内存,最后存入vector的内容全是混乱的,后续遍历自然会触发未定义行为(比如SIGINT)。
2. 画蛇添足的'\0'
string类型本身会自动管理末尾的终止符,你手动给每个字符串加'\0'完全没必要,反而会让输出出现奇怪的空字符或乱码,干扰程序正常运行。
3. 逆序遍历的循环逻辑有漏洞
原循环:
for (vector<string>::iterator it = strVector.end()-1 ; it != strVector.begin(); it--)
- 如果输入的内容是空的(比如直接按EOF),
strVector.end()-1就是非法迭代器(空容器的end和begin是同一个位置,减1直接越界),这会直接触发崩溃或SIGINT。 - 循环条件
it != strVector.begin()会漏掉第一个元素(也就是原输入的第一行),而且遍历到begin就停止,无法完成完整的逆序输出。
4. 读取EOF时写入了无效字符
getc(stdin)返回的EOF是int类型的-1,你直接把它转成char加到字符串里,会存入一个无效的0xFF字符,导致后续的字符串查找和截取逻辑出错。
二、一步步修复代码
1. 修复字符读取逻辑
先判断是否为EOF,再添加有效字符到字符串:
int c; while ((c = getc(stdin)) != EOF) { strLines += static_cast<char>(c); }
2. 修正substr的使用方式
正确计算截取长度,并且去掉多余的'\0':
string strToPush = strLines.substr(oldIndex, newIndex - oldIndex); strVector.push_back(strToPush);
3. 用更安全的方式逆序遍历
推荐用反向迭代器,这完全符合你最初的思路,而且不需要手动处理迭代器边界,安全又简洁:
for (vector<string>::reverse_iterator it = strVector.rbegin(); it != strVector.rend(); ++it) { cout << *it << endl; // 如果想保留原输入的换行符,改成cout << *it;就行 }
要是你坚持用普通迭代器,记得先判断vector是否为空,再调整循环条件确保遍历所有元素:
if (!strVector.empty()) { for (auto it = strVector.end() - 1;; --it) { cout << *it; if (it == strVector.begin()) break; } }
4. 处理最后一行无换行的情况
原代码会漏掉没有以换行结尾的最后一行,新增这个逻辑补上:
if (newIndex == string::npos) { // 如果还有未处理的内容,添加最后一行 if (oldIndex < strLines.size()) { strVector.push_back(strLines.substr(oldIndex)); } break; }
三、完整的修复后代码
#include <iostream> #include <vector> #include <string> using namespace std; int main() { string strLines; int c; // 修复字符读取,避免写入EOF无效字符 while ((c = getc(stdin)) != EOF) { strLines += static_cast<char>(c); } size_t oldIndex = 0; size_t newIndex; vector<string> strVector; // 正确截取每行内容,处理最后一行无换行的情况 while (true) { newIndex = strLines.find('\n', oldIndex); if (newIndex == string::npos) { if (oldIndex < strLines.size()) { strVector.push_back(strLines.substr(oldIndex)); } break; } string strToPush = strLines.substr(oldIndex, newIndex - oldIndex); strVector.push_back(strToPush); oldIndex = newIndex + 1; } // 反向迭代器安全逆序输出 for (auto it = strVector.rbegin(); it != strVector.rend(); ++it) { cout << *it << endl; } return 0; }
额外提示
- 在VSCode终端输入EOF的方式:Windows按
Ctrl+Z,Linux/macOS按Ctrl+D。 - C++11及以上版本可以用
auto简化迭代器声明,代码会更清爽。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

