c++多次调用时 getline() 不等待来自控制台的输入
我试图从控制台获取一些用户输入参数,两个字符串,两个整数和一个双精度。我尝试使用的相关代码是这样的:
#include <string>
#include <iostream>
using namespace std;
// ...
string inputString;
unsigned int inputUInt;
double inputDouble;
// ...
cout << "Title: ";
getline(cin, inputString);
tempDVD.setTitle(inputString);
cout << "Category: ";
getline(cin, inputString);
tempDVD.setCategory(inputString);
cout << "Duration (minutes): ";
cin >> inputUInt;
tempDVD.setDuration(inputUInt);
cout << "Year: ";
cin >> inputUInt;
tempDVD.setYear(inputUInt);
cout << "Price: $";
cin >> inputDouble;
tempDVD.setPrice(inputDouble);
但是,在运行程序时,代码不会等待输入第一个 inputString,而是直到第二次 getline() 调用才停止。因此控制台输出如下所示:
标题:类别:
光标出现在类别后面。如果我现在输入,程序就会跳转到年份输入,不允许我输入多个字符串。这里发生了什么事?
I'm attempting to get a few user-input parameters from the console, two strings, two ints and a double. The relevant code I'm trying to use is this:
#include <string>
#include <iostream>
using namespace std;
// ...
string inputString;
unsigned int inputUInt;
double inputDouble;
// ...
cout << "Title: ";
getline(cin, inputString);
tempDVD.setTitle(inputString);
cout << "Category: ";
getline(cin, inputString);
tempDVD.setCategory(inputString);
cout << "Duration (minutes): ";
cin >> inputUInt;
tempDVD.setDuration(inputUInt);
cout << "Year: ";
cin >> inputUInt;
tempDVD.setYear(inputUInt);
cout << "Price: $";
cin >> inputDouble;
tempDVD.setPrice(inputDouble);
However, when running the program, instead of waiting for the first inputString to be entered, the code doesn't stop until the second getline() call. Thus the console output looks like this:
Title: Category:
with the cursor appearing after category. If I input now, the program then jumps ahead to the year input, not allowing me to enter more than one string. What's happening here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
问题是您将对 getline() 的调用与运算符 >> 的使用混合在一起。
请记住运算符>>忽略前导空白,因此将正确地继续跨行边界。但在成功检索输入后停止读取,因此不会吞掉尾随的“\n”字符。因此,如果您在 >> 之后使用 getline()除非你小心(首先删除未读取的 '\n' 字符),否则你通常会得到错误的结果。
诀窍是不要使用这两种类型的输入。选择合适的一项并坚持下去。
如果都是数字(或与运算符 >> 配合良好的对象),则只需使用运算符 >> (注意字符串是唯一与输入/输出不对称的基本类型(即不能很好地发挥作用))。
如果输入包含需要 getline() 的字符串或内容组合,则仅使用 getline() 并从字符串中解析出数字。
The problem is you are mixing calls to getline() with the use of the operator >>.
Remember that operator >> ignored leading white space so will correctly continue across lines boundaries. But stops reading after the input has successfully been retrieved and thus will not swallow trailing '\n' characters. Thus if you use a getline() after a >> you usually get the wrong thing unless you are careful (to first remove the '\n' character that was not read).
The trick is to not use both types of input. Pick the appropriate one and stick to it.
If it is all numbers (or objects that play nice with operator >>) then just use operator >> (Note string is the only fundamental type that is not symmetric with input/output (ie does not play nicely)).
If the input contains strings or a combination of stuff that will require getline() then only use getline() and parse the number out of the string.
使用
或,如 @kernald 提到的使用
您可以在使用 getline() 之前
You can use
or as @kernald mentioned use
before using getline()
您需要刷新输入缓冲区。可以通过 cin.clear(); 来完成cin.sync();。
You need to flush the input buffer. It can be done with
cin.clear(); cin.sync();
.如前所述使用 cin.clear() 并使用正确的错误处理:
Use
cin.clear()
as mentioned and use proper error handling:如果用户在 getline 之前的 cin 中的 \n 之前输入空格,则仅 ignore 本身是不够的,因此您必须使用此代码而不是单独的 ignore() 。例如 12345 \t \n 将不再起作用。
所有未处理的字符都必须被忽略。
在 cin 和 getline 之间使用它。
If user inputs a space before \n in previous cin before getline, only ignore itself wouldn't be enough so you have to use this code instead of ignore() alone. For example 12345 \t \n will not work anymore.
All unprocessed characters must be ignored.
Use this between cin and getline.
也适用于
ws
。在使用 cin 命令读取数据后,您可以使用 getline(cin >> ws, inputString)) 来吃掉空格或换行符。Also works with
ws
. You can usegetline(cin >> ws, inputString)
) to eat the whitespaces or the newlines after reading data withcin
command.将 getline() 与输入流混合通常是一件坏事。理论上可以手动处理使用流留下的脏缓冲区,但这是绝对应该避免的不必要的痛苦。
您最好使用控制台库来获取输入,这样可以为您抽象出脏工作。
看看 TinyCon。您可以使用静态方法tinyConsole::getLine() 来代替getline 和stream 调用,并且可以根据需要多次使用它。
您可以在这里找到信息:
https://sourceforge.net/projects/tinycon/
Mixing getline() with input streams in generally a bad thing to do. It's theoretically possible to manually handle the dirty buffers left over by using streams, but it's an unnecessary pain that should definitely be avoided.
You are better off using a console library to grab your input, this way the dirty-work can be abstracted for you.
Take a look at TinyCon. You can just use the static method tinyConsole::getLine() in replace of your getline and stream calls, and you can use it as many times as you'd like.
You can find information here:
https://sourceforge.net/projects/tinycon/
cin.sync();
使用这个代替 cin.ignore(
效果最好。
cin.sync();
use this instead of cin.ignore(
works best.
函数_______将返回最后读取的字符,并将内部指针移动-1个字符。
3.flush()
4.putback()
The function_______ will return the last read character and will move the inside pointer one with -1 char.
3.flush()
4.putback()