为什么STD :: getline()在格式提取后跳过输入?
我有以下代码,这些代码提示用户的猫的年龄和名称:
#include <iostream>
#include <string>
int main()
{
int age;
std::string name;
std::cin >> age;
std::getline(std::cin, name);
if (std::cin)
{
std::cout << "My cat is " << age << " years old and their name is " << name << std::endl;
}
}
我发现年龄已成功阅读,但没有名字。这是输入和输出:
输入: “ 10” “晶须先生” 输出: “我的猫已经10岁了,他们的名字就是”
为什么从输出中省略了名称?我给出了适当的输入,但是代码以某种方式忽略了它。为什么会发生这种情况?
I have the following piece of code that prompts the user for their cat's age and name:
#include <iostream>
#include <string>
int main()
{
int age;
std::string name;
std::cin >> age;
std::getline(std::cin, name);
if (std::cin)
{
std::cout << "My cat is " << age << " years old and their name is " << name << std::endl;
}
}
What I find is that the age has been successfully read, but not the name. Here is the input and output:
Input: "10" "Mr. Whiskers" Output: "My cat is 10 years old and their name is "
Why has the name been omitted from the output? I've given the proper input, but the code somehow ignores it. Why does this happen?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
为什么会发生这种情况?
这与您自己提供的输入无关,而与默认行为
std :: getline()
具有。当您提供年龄的输入(std :: cin&gt; age
)时,您不仅提交了以下字符,而且在输入输入:从终端提交时,当您选择 enter 或返回时,始终将newline附加到您的输入中。它也用于文件中,用于朝着下一行移动。提取到
age
之前,新线将留在缓冲区中,直到下一个I/O操作被丢弃或读取为止。当控件流达到std :: getline()
时,它将看到“ \nmr。whiskers”
,并且开始时的newline将被丢弃,但是输入操作会立即停止。之所以发生的原因是因为std :: getline()的作业是尝试读取字符并在找到新线时停止。因此,其余的输入将留在缓冲区未读。
解决方案
cin.ignore()
要解决此问题,一个选项是在执行
std :: getline()
之前跳过newline。您可以通过调用std :: cin.ignore()
在第一个输入操作后来执行此操作。它将丢弃下一个字符(newline字符),以便不再妨碍它。std :: ws
丢弃空格的另一种方法是使用
std :: WS
函数,该功能是一种操纵器,旨在从输入开始时提取和丢弃领先的空格流:std :: cin&gt;&gt; std :: ws
表达式在std :: getline()
呼叫之前(以及std :: cin&gt;&gt; egt; age
呼叫)删除了新线字符。不同之处在于
ignore()
仅放弃1个字符(或给出参数时n个字符),而std :: WS
继续忽略空格,直到找到一个非 - 空格角色。因此,如果您不知道在接下来的标记之前将要考虑使用该空间有多少,则应考虑使用此问题。匹配操作
时,当您遇到这样的问题时,通常是因为您将格式化的输入操作与未进行输入操作相结合。格式的输入操作是您进行输入并为某种类型的格式格式化时。这就是
操作员&gt;&gt;()
是为了。除std :: getline()
,std :: cin.read()
,std :: cin.get( )
等。这些功能不在乎输入的格式,而仅处理原始文本。如果您坚持使用单一类型的格式,则可以避免此烦人的问题:
或者,
如果选择使用未形式的操作读取所有内容作为字符串,则可以将其转换为适当的类型。
Why does this happen?
This has little to do with the input you provided yourself but rather with the default behavior
std::getline()
has. When you provided your input for the age (std::cin >> age
), you not only submitted the following characters, but also an implicit newline was appended to the stream when you typed Enter:A newline is always appended to your input when you select Enter or Return when submitting from a terminal. It is also used in files for moving toward the next line. The newline is left in the buffer after the extraction into
age
until the next I/O operation where it is either discarded or read. When the flow of control reachesstd::getline()
, it will see"\nMr. Whiskers"
and the newline at the beginning will be discarded, but the input operation will stop immediately. The reason this happens is because the job ofstd::getline()
is to attempt to read characters and stop when it finds a newline. So the rest of your input is left in the buffer unread.Solution
cin.ignore()
To fix this, one option is to skip over the newline before doing
std::getline()
. You can do this by callingstd::cin.ignore()
after the first input operation. It will discard the next character (the newline character) so that it is no longer in the way.std::ws
Another way to discard the whitespace is to use the
std::ws
function which is a manipulator designed to extract and discard leading whitespace from the beginning of an input stream:The
std::cin >> std::ws
expression is executed before thestd::getline()
call (and after thestd::cin >> age
call) so that the newline character is removed.The difference is that
ignore()
discards only 1 character (or N characters when given a parameter), andstd::ws
continues to ignore whitespace until it finds a non-whitespace character. So if you don't know how much whitespace will precede the next token you should consider using this.Match the operations
When you run into an issue like this it's usually because you're combining formatted input operations with unformatted input operations. A formatted input operation is when you take input and format it for a certain type. That's what
operator>>()
is for. Unformatted input operations are anything other than that, likestd::getline()
,std::cin.read()
,std::cin.get()
, etc. Those functions don't care about the format of the input and only process raw text.If you stick to using a single type of formatting then you can avoid this annoying issue:
or
If you choose to read everything as strings using the unformatted operations you can convert them into the appropriate types afterwards.
如果您以以下方式更改初始代码,一切都会好的:
Everything will be OK if you change your initial code in the following way:
发生这种情况是因为隐式线feed也称为newline字符
\ n
被附加到终端中的所有用户输入上,因为它告诉流开始新行。您可以使用std :: getline
检查多行用户输入时。std :: getline
的默认行为将从输入流对象(std :: cin 在这种情况下。
This happens because an implicit line feed also known as newline character
\n
is appended to all user input from a terminal as it's telling the stream to start a new line. You can safely account for this by usingstd::getline
when checking for multiple lines of user input. The default behavior ofstd::getline
will read everything up to and including the newline character\n
from the input stream object which isstd::cin
in this case.我真的很想知道。 C ++具有专门的功能,可以吃掉任何剩余的或任何白色空间。称为 std :: ws 。然后,您可以简单地使用
它应该是IDOMANT方法。对于应使用的格式化到未格式化的输入之间的每个跨源。
如果我们不是在谈论白色空间,而是输入预期数字的字母,那么我们应该遵循CPP参考并使用
.ignore(std :: Numeric_limits&lt; std :: streamSize&gt; :: max() ,'\ n');
消除错误的东西。请阅读在这里
I am really wondering. C++ has a dedicated function for eating up any remaining or whatever white spaces. It is called std::ws. And then, you can simply use
That should be the idomatic approach. For each transistion between formatted to unformatted input that should be used.
If we are not talking about white spaces, but entering for example letters where a number is expected, then we should follow the CPP reference and use
.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
to eliminate the wrong stuff.Please read here
由于上面的每个人都回答了输入
10 \ nmr晶须\ n
的问题,因此我想回答另一种方法。上面的所有解决方案都发布了代码,以便如果缓冲区像10 \ nmr晶须\ n
。但是,如果我们不知道用户在给出输入方面的行为怎么办。用户可以键入10 \ n \ nmr。 Whisker \ n
或10 \ n \ n先生Whisker \ n
误认为。在这种情况下,上面的代码可能行不通。因此,我使用以下功能进行字符串输入来解决问题。因此,答案将是:
额外:
如果用户输入
a \ n10 \ n \ nmr。威士忌
;要检查
int
输入是否有效,可以使用此功能检查int
输入(如果给出char
,程序将具有不确定的行为作为输入而不是int
):Since everyone above has answered the problem for input
10\nMr Whisker\n
, I would like to answer a different approach. All the solution above published the code for if the buffer is like10\nMr Whisker\n
. But what if we don't know how user will behave in giving input. The user might type10\n\nMr. Whisker\n
or10 \n\n Mr. whisker\n
by mistake. In that case, codes above may not work. So, I use the function below to take string input to address the problem.So, the answer would be:
Extra:
If user inputs
a \n10\n \nmr. whiskey
;To check whether
int
input is valid or not, this function can be used to checkint
input (program will have undefined behavior ifchar
is given as input instead ofint
):