我是编码的新手,我正在尝试使用嵌套的do while
语句进行较长的if
循环,但是在使循环实际循环时遇到了问题。
我没有直接在代码很长的项目上获得帮助,而是制作了一个类似它的简单版本。它也不会循环。它将结束并询问用户是否要重试,但是输入“ y”时,它将忽略if语句。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string sodaChoice;
char answer = 'n';
do
{
cout << "Please choose your favorite soda from the following: Rootbeer, Diet Coke, Coke, Sprite" << "\n";
getline(cin, sodaChoice);
if (sodaChoice == "Rootbeer")
{
cout << "Me too!" << "\n";
}
else if (sodaChoice == "Diet")
{
cout << "Not me :(" << "\n";
}
else if (sodaChoice == "Coke")
{
cout << "It's alright" << "\n";
}
else if (sodaChoice == "Sprite")
{
cout << "only if I'm sick" << "\n";
}
else
{
cout << "That was not on the list";
}
cout << "would you like to try again?";
cin >> answer;
} while (answer == 'y'|| answer == 'Y');
return 0;
}
我以为也许我需要在if语句周围的do循环中执行一个do循环,但是后来我不知道该怎么做。任何帮助,将不胜感激。我花了很多小时试图弄清楚。
我试图问我的老师,但是我的大学从院长根据她的书写的一些通用课程中教书。他对帮助或教学不是很热心。
编辑: 谢谢大家的回答!至于这是一个重复的问题,我尚未学习cin.ignore,所以我不知道它与我的问题有关。谢谢大家教我!
答案 0 :(得分:13)
使用
cin >> answer;
您准确地读取了一个字符。问题是您在写答案时至少输入了两个个字符。实际的'y'
或'n'
plus Enter 键,它作为换行符添加到输入缓冲区中。
此换行符随后在下一个getline
调用中作为空行读取。
有一些解决此问题的方法,例如在读入answer
之后使用ignore
。或者,如果您只想输入一个单词,则也可以将>>
用作sodaChoice
的格式化输入,因为默认情况下它将跳过前导空白(如换行符)。
答案 1 :(得分:7)
在用户表现良好并仅输入“ y”或“ n”后跟换行符的情况下,现有答案是正确的。
通过对.ignore()调用进行修改,我们可以要求它忽略所有字符,直到下一个换行符为止,从而增加一点安全性:
您需要在翻译单元的顶部添加此标头,包括
#include <limits>
您需要在cin >> answer
之前添加以下行:
// consumes and ignores as many characters as necessary until a newline.
// The newline is also consumed.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
此处有测试输入的完整程序:
http://coliru.stacked-crooked.com/a/996e77559590ad6d
不幸的是,计算机科学老师对计算机科学一无所知并不稀奇。不必担心这一点,也不要让它让您停止学习如何编写软件-这只是一个事实,即优秀的软件工程师的薪水比出色的老师高得多。
以下是一些有用的参考资料:https://en.cppreference.com/w/cpp/io/basic_istream/ignore
答案 2 :(得分:5)
我将提出与其他答案完全相反的建议。我认为与其使用cin.ignore
来跳过阅读的字符之后的多余字符,不如使用getline()
完成所有阅读并完全忘记cin >> somevar
。
有两个原因:
通过cin >> somevar
获得的格式化输入将忽略前导空格,包括换行符。如果用户在空白行上按 Enter ,则该程序不会执行任何操作,但仍需要进一步的输入。这不是CLI程序用户所期望的!通常的期望是 Enter 完成输入,而空输入应该导致程序使用默认值,或者抱怨输入无效。使用cin >> somevar
,您将无法执行任何操作。
格式化的输入将所有不匹配的输入留在缓冲区中。在您的示例中,读取单个字符至少会留下以下换行符,但其他类型的输入也会发生同样的情况。读取数字(使用int i; cin >> i;
)会在数字等待下一个输入操作之后留下任何内容,因此输入123 abc
将返回123
,而abc
将出现在下一个输入操作上输入操作。
此问题的根本原因是默认情况下,命令行终端处于基于行的模式。在输入完整行之前,程序或库函数看不到来自操作系统的任何输入。 (cin.ignore()
当然可以帮助您解决这个问题,但不能解决第一点。)
使用getline()
与底层机制完全匹配,可以让您处理空输入(以及在读取int
时告诉零和非数字之间的差),并自动处理尾随的垃圾。但是,您必须将读取的字符串手动转换为实际所需的任何字符串。
在您的情况下,您可以将循环条件更改为类似以下内容:
string answer;
...
getline(cin, answer);
} while (answer == "y" || answer == "Y");
如果您需要一个数字,则可以使用例如int num = std::stoi(str)
。
(在C语言中,如果使用scanf()
进行用户输入也会发生同样的情况,同样,最好使用fgets()
然后用sscanf()
解析字符串,这样可以得到相同的选项,但处理行缓冲。我对C ++不太熟悉,因此我无法说出如何使cin >> somevar
的行完全等于getline()
。)
答案 3 :(得分:0)
由于您正在从类型char
的用户那里获取输入,但是每次击键Enter
时,它就会将换行符(\n
)分配给变量answer
。 >
您可以通过在输入行之后添加一行来忽略它
cin.ignore();
您可以阅读this了解更多详细信息。