嘿,我正在尝试编写一个程序,它将接受来自人的新任务,将其添加到堆栈,能够显示任务,能够将该堆栈保存到文本文件,然后阅读文本文件。当我尝试接受来自用户的输入时,每当你输入一个带有空格的字符串时,问题就出现了,菜单选择只做循环。我需要一种方法来解决这个问题。任何帮助将不胜感激。
// basic file io operations
#include <iostream>
#include <fstream>
#include <stack>
#include <string>
using namespace std;
int main () {
//Declare the stack
stack<string> list;
//Begin the loop for the menu
string inputLine;
cout << "Welcome to the to-do list!" << endl;
//Trying to read the file
ifstream myfile ("to-do.txt");
if(myfile.is_open()){
//read every line of the to-do list and add it to the stack
while(myfile.good()){
getline(myfile,inputLine);
list.push(inputLine);
}
myfile.close();
cout << "File read successfully!" << endl;
} else {
cout << "There was no file to load... creating a blank stack." << endl;
}
int option;
//while we dont want to quit
while(true){
//display the options for the program
cout << endl << "What would you like to do?" << endl;
cout << "1. View the current tasks on the stack." << endl;
cout << "2. Remove the top task in the stack." << endl;
cout << "3. Add a new task to the stack." << endl;
cout << "4. Save the current task to a file." << endl;
cout << "5. Exit." << endl << endl;
//get the input from the user
cin >> option;
//use the option to do the necessary task
if(option < 6 && option > 0){
if(option == 1){
//create a buffer list to display all
stack<string> buff = list;
cout << endl;
//print out the stack
while(!buff.empty()){
cout << buff.top() << endl;
buff.pop();
}
}else if (option == 2){
list.pop();
}else if (option == 3){
//make a string to hold the input
string task;
cout << endl << "Enter the task that you would like to add:" << endl;
getline(cin, task); // THIS IS WHERE THE ISSUE COMES IN
cin.ignore();
//add the string
list.push(task);
cout << endl;
}else if (option == 4){
//write the stack to the file
stack<string> buff = list;
ofstream myfile ("to-do.txt");
if (myfile.is_open()){
while(!buff.empty()){
myfile << buff.top();
buff.pop();
if(!buff.empty()){
myfile << endl;
}
}
}
myfile.close();
}else{
cout << "Thank you! And Goodbye!" << endl;
break;
}
} else {
cout << "Enter a proper number!" << endl;
}
}
}
答案 0 :(得分:3)
您必须在选择选项后立即添加cin.ignore()
:
//get the input from the user
cin >> option;
cin.ignore();
cin.ignore()
之后getline
不需要 getline(cin, task); // THIS IS WHERE THE ISSUE COMES IN
//cin.ignore();
。
options
问题出在cin.ignore()
- 如果您之后没有调用{{1}},则选项将包含行尾,循环将继续...
我希望这会有所帮助。
答案 1 :(得分:1)
不要这样做:
while(myfile.good())
{
getline(myfile,inputLine);
list.push(inputLine);
}
在您尝试通过EOF读取之前,不会设置EOF标志。最后一行读取读取到达(不过去)EOF。因此,如果你输入零,myfile.good()为真,循环就会消失。然后你尝试读取一行,它会失败,但你仍然会推动。
读取文件中所有行的标准方法是:
while(getline(myfile,inputLine))
{
list.push(inputLine);
}
这样只有在文件包含数据时才会输入循环。
你的另一个问题似乎源于你有:
std::getline(std::cin,task); // THIS is OK
std::cin.ignore(); // You are ignoring the next character the user inputs.
// This probably means the next command number.
// This means that the next read of a number will fail
// This means that std::cin will go into a bad state
// This means no more input is actually read.
所以只需删除cin.ignore()行,一切都会正常工作。
答案 2 :(得分:1)
而不是使用“&gt;&gt;”直接在您的流上,您可以考虑使用getline,然后尝试从中获取您的选项。是的,它不那么“有效”,但在这种情况下效率通常不是问题。
你知道,问题是用户可以在这里输入一些愚蠢的东西。例如,他们可以输入类似“两个”的东西,点击输入,然后你的程序就会变得合适,因为它乐意继续尝试一遍又一遍地翻译一个空选项。用户唯一可靠的设置方式(以及推荐使用ignore()
推荐的方式)就是杀死你的程序。一个表现良好的程序不会以这种方式响应错误的输入。
因此,您最好的选择不是编写脆弱的代码,这些代码可以严重破坏最适度的用户无知/故障,而是编写可以优雅地处理错误情况的代码。你不能希望用户输入一个数字,然后输入换行符。总有一天,你会打得很差。
因此,您有两种选择来阅读您的选项。首先,读取用户的完整行,确保流仍然良好,然后将您获得的字符串转换为流并尝试从中读取整数,确保此其他流仍然良好。第二个选项,尝试读取一个数字,验证流仍然是好的,读取一行并确保流仍然是好的,并且你的字符串是空的(或者如果它不是你的选择就忽略它)。 / p>
答案 3 :(得分:1)
@Vladimir是对的。这是bug背后的机制:
当您输入选项'3'时,实际放入流中的是“3 \ n”。 cin >> option
消耗“3”并留下“\ n”。在getline()
等待用户输入后,ignore()
会消耗“\ n”并呼叫getline()
。
正如您所看到的,事件序列已经不是您所期望的。
现在,当ignore()等待输入时,你输入你的行。您输入的那一行将是“cin&gt;&gt;选项。
如果您只给它一个符号,ignore()将为您处理它,并且将正确读取选项。但是,如果您为其指定非数字符号,则在尝试读取该选项时,stream将设置failbit。从那时起,您的流将拒绝做任何事情。任何&lt;&lt;或者getline不会在它们应该更改的变量中设置任何新值。你将保持3选项和“”在任务中,紧紧循环。
要做的事情:
答案 4 :(得分:0)
我只是找到了一种方法来破解它,而不是最伟大的但它有效。创建一个字符数组,然后接受数组中的输入,然后将所有内容放入数组中。
char buff[256];
cout << endl << "Enter the task that you would like to add:" << endl;
cin >> task;
task += " ";
cin.getline(buff, 256);
for(int i = 1; buff[i] != 0; i++){
task += buff[i];
}