Mac终端g++编译C++待办列表程序遇两处运行错误求助
C++待办列表程序错误修复方案
问题根源分析
1. 删除任务偶发报错、第二次添加任务报错的核心原因
函数参数使用了值传递,比如addToDoItems和deleteToDoItems的参数定义为vector<string>(toDoList),这意味着函数内部操作的是原vector的副本,而非原数据本身:
- 删除任务时,副本的任务数量和原vector不一致,若用户输入的任务编号超出副本的有效范围,会触发
out_of_range异常导致报错; - 第二次添加任务时,函数修改的是副本,原vector数据完全没更新,后续操作基于无效的副本数据,必然引发错误。
2. 第二次添加任务报错的额外诱因
cin >> userInput执行后,输入缓冲区会残留换行符,后续调用getline(cin, userInput)时会直接读取这个空行,导致userInput为空字符串,执行userInput.at(0)时触发越界异常。
具体修复步骤
- 将函数参数改为引用传递
把所有函数声明和定义的参数从vector<string>(toDoList)改为vector<string>& toDoList,让函数直接操作原vector:
void addToDoItems(vector<string>& toDoList); void deleteToDoItems(vector<string>& toDoList);
- 处理输入缓冲区残留的换行符
在每次使用cin >>之后,添加代码清除缓冲区的换行符,需先包含<limits>头文件:
#include <limits>
示例:在addToDoItems中cin >> userInput之后添加:
cin.ignore(numeric_limits<streamsize>::max(), '\n');
- 添加输入验证,防止删除任务时越界
在删除任务的循环中,先检查用户输入的任务编号是否在有效范围(1到当前列表任务数),无效则提示重新输入:
while (taskNumToDelete != -1) { if (taskNumToDelete < 1 || taskNumToDelete > toDoList.size()) { cout << "无效的任务编号,请输入1到" << toDoList.size() << "之间的数字,或输入-1退出:"; cin >> taskNumToDelete; cout << endl; continue; } toDoList.erase(toDoList.begin() + taskNumToDelete - 1); cout << "请输入下一个已完成任务的编号(输入-1查看剩余任务):"; cin >> taskNumToDelete; cout << endl; }
修改后的完整代码
#include <iostream> #include <vector> #include <string> #include <limits> using namespace std; void addToDoItems(vector<string>& toDoList); void deleteToDoItems(vector<string>& toDoList); int main(){ vector<string> toDoList; addToDoItems(toDoList); return 0; } void addToDoItems(vector<string>& toDoList) { int count = toDoList.size() + 1; char capitalizeFirstLetter; string userInput; // 清除之前cin操作残留的换行符 cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout << "\n请输入要添加的任务:"; getline(cin, userInput); cout << endl; while (userInput != "q") { if (userInput.empty()) { cout << "任务不能为空,请重新输入,或输入q退出:"; getline(cin, userInput); cout << endl; continue; } capitalizeFirstLetter = toupper(userInput.at(0)); userInput.erase(0,1); userInput = to_string(count) + ". " + capitalizeFirstLetter + userInput; toDoList.push_back(userInput); cout << "添加另一个任务或按q完成添加:"; getline(cin, userInput); cout << endl; ++count; } cout << "你今天需要完成的任务:\n" << endl; for (int i = 0; i < toDoList.size(); ++i) { cout << toDoList.at(i) << endl; } cout << "\n按d可以标记完成任务,按其他键退出:"; cin >> userInput; cout << endl; if (userInput == "d") { deleteToDoItems(toDoList); } else { cout << "祝你愉快!\n" << endl; } } void deleteToDoItems(vector<string>& toDoList) { int taskNumToDelete; int count = 1; string tasksLeft; string userInput; cout << "请输入已完成任务的编号(参考上方列表):"; cin >> taskNumToDelete; cout << endl; while (taskNumToDelete != -1) { if (taskNumToDelete < 1 || taskNumToDelete > toDoList.size()) { cout << "无效编号,请输入1到" << toDoList.size() << "之间的数字,或输入-1退出:"; cin >> taskNumToDelete; cout << endl; continue; } toDoList.erase(toDoList.begin() + taskNumToDelete - 1); cout << "请输入下一个已完成任务的编号(输入-1查看剩余任务):"; cin >> taskNumToDelete; cout << endl; } if (toDoList.size() > 0) { if (toDoList.size() == 1) { cout << "快完成了!你还有" << toDoList.size() << "个任务要做!\n" << endl; } else { cout << "快完成了!你还有" << toDoList.size() << "个任务要做!\n" << endl; } for (int i = 0; i < toDoList.size(); ++i) { tasksLeft = toDoList.at(i); // 找到第一个点的位置,删除编号部分,避免多位数编号处理错误 size_t dotPos = tasksLeft.find("."); if (dotPos != string::npos) { tasksLeft = tasksLeft.substr(dotPos + 2); } cout << count << ". " << tasksLeft << endl; // 更新vector中的编号,避免后续操作编号混乱 toDoList[i] = to_string(count) + ". " + tasksLeft; ++count; } cout << endl; cout << "按d继续标记完成任务,按a添加新任务,按其他键退出:"; cin >> userInput; cout << endl; if (userInput == "d") { deleteToDoItems(toDoList); } else if(userInput == "a") { addToDoItems(toDoList); } else { cout << "祝你愉快!\n" << endl; } } else { cout << "恭喜!你完成了所有任务,可以放松一下了:)\n" << endl; } }
内容的提问来源于stack exchange,提问作者Nicholas Davies
相关产品推荐
相关产品推荐

