提问人:Jeremy Fisher 提问时间:11/28/2021 最后编辑:einpoklumJeremy Fisher 更新时间:11/28/2021 访问量:782
为什么 cin 和 getline 表现出不同的阅读行为?
Why do cin and getline exhibit different reading behavior?
问:
作为参考,我已经看过为什么 std::getline() 在格式化提取后跳过输入?
我想了解 cin 和 getline 行为。我想象 cin 和 getline 是通过输入缓冲区的循环来实现的,每次迭代都会增加一个游标。一旦输入缓冲区的当前元素等于某个“停止”值(“”或“\n”表示cin,“\n”表示getline),循环就会中断。
我的问题是 cin 和 getline 的读取行为之间的区别。使用 cin,它似乎停在“\n”处,但它会在中断循环之前递增光标。例如
string a, b;
cin >> a;
cin >> b;
cout << a << "-" << b << endl;
// Input: "cat\nhat"
// Output: "cat-hat"
因此,在上面的代码中,第一个 cin 一直读取到“\n”。一旦它击中“\n”,它就会将光标递增到下一个位置“h”,然后再中断循环。然后,下一个 cin 操作开始从“h”读取。这允许下一个 cin 实际处理字符,而不仅仅是破坏。
当 getline 与 cin 混合时,这不是行为。
string a, b;
cin >> a;
getline(cin, b);
cout << a << "-" << b << endl;
// Input: "cat\nhat"
// Output: "cat-"
在此示例中,cin 读取至“\n”。但是当 getline 开始读取时,它似乎是从“\n”而不是“h”读取的。这意味着光标没有前进到“h”。因此,getline 处理了 “\n” 并将光标前进到 “h”,但实际上并没有将 getline 保存到 “b”。
因此,在一个示例中,cin 似乎将光标推进到“\n”处,而在另一个示例中,它没有。 getline 也表现出不同的行为。例如
string a, b;
getline(cin, a);
getline(cin, b);
cout << a << "-" << b << endl;
// Input: "cat\nhat"
// Output: "cat-hat"
现在,getline 实际上将光标推进到“\n”上。为什么会有不同的行为,当涉及到分身字符时,cin 和 getline 的实际实现是什么?
答:
CIN 和 GetLine 的读取行为。
cin
不“阅读”任何东西。 是输入流。 正在从中读取。 从输入流中读取。格式化的提取运算符 从输入流中读取。正在阅读的是 和 . 没有自己的读数。这是正在阅读的内容。cin
cin
getline
>>
>>
std::getline
std::cin
第一个 CIN 读取直到“\n”。一旦它击中“\n”,它就会递增 光标到下一个位置
不,它没有。第一个运算符读取直到 ,但不读取它。 仍未读。>>
\n
\n
第二个运算符以换行符开始读取。运算符在提取预期值之前跳过输入流中的所有空格。>>
>>
您缺少的细节是在从输入流中提取值之前跳过空格(如果有),而不是之后。>>
现在,在提取格式化值之前,肯定有可能在输入流中找不到空格。如果的任务是提取一个 ,并且输入流刚刚打开,它位于文件的开头,并且文件中的第一个字符是 ,那么,它只是根本不跳过任何空格。>>
>>
int
1
>>
最后,它不会跳过任何空格,它只是从输入流中读取,直到它读取(或到达输入流的末尾)。std::getline
\n
评论
\n
std::getline
>>
getline
getline
\n
std::string
std::getline
\n
TL的;DR:这是因为 How 是面向内部的,而 GetLine 是面向线的。std::cin
从历史上看,在 C 的标准库中,我们有函数和:scanf()
getline()
当你告诉期待一个字符串时,它
scanf()
...停在空白处或最大场宽处,以先到者为准。
更一般地说,
大多数转换 [例如,字符串的读取] 会丢弃初始空格字符
(摘自
scanf()
手册页)当您调用时,它:
getline()
阅读一整行......包含文本的缓冲区 ...包括换行符(如果已找到)。
(摘自
getline()
手册页)
现在,C++的机制被格式化的输入匹配所取代,但具有类型安全性。(实际上,作为替代品是相当有问题的,但现在没关系了。作为 的替代品,它继承了它的许多功能,包括不喜欢拾取空白。std::cin
scanf()
std::cin
std::cout
scanf()
因此,就像 一样,为字符串运行将在字符之前停止,并将该换行符保留在输入流中以备将来使用。此外,就像 一样,>>运算符跳过前导空格,因此,如果您再次使用它,则将跳过 ,并且从下一行的第一个非空格字符开始拾取下一个字符串。scanf()
std::cin >> a
a
\n
scanf()
std::cin
\n
使用 ,您可以获得与过去几十年完全相同的行为。std::getline()
getline()
PS - 您可以使用 std::cin
的 skipws format-flag 来控制空格跳过行为
评论
\n
\n
评论
cin
operator>>
cin
并且不会表现出不同的行为。格式化提取(使用运算符)都与流交互,您看到的是它们与(和任何流)的交互方式不同。他们这样做是因为它们的指定方式不同。 跳过空格,读取值(如果可以),并在到达空格时停止。 (默认情况下)继续读取,直到遇到换行符 - 并丢弃换行符。将它们一起使用可能会导致与某些用户输入的意外交互。getline()
getline()
<<
cin
operator<<()
getline()