我对这两段代码之间的区别有疑问:
char buffer5[5];
cin.get(buffer5, 5);
cout << buffer5;
cin.get(buffer5, 5);
cout << buffer5;
Run Code Online (Sandbox Code Playgroud)
和
char buffer4;
while (cin.get(buffer4))
{
cout << buffer4;
}
Run Code Online (Sandbox Code Playgroud)
在第一段代码中,代码获得5个字符并将其放入buffer5中.但是,由于您按Enter键,因此在调用get()时不会将换行符放入流中,因此程序将终止并且不会要求您再换一轮5个字符.
在第二段代码中,cin.get()等待输入流的输入,因此循环不会终止(我认为).假设我在输入流中输入"Apple".这将在输入流中放入5个字符,循环将所有字符打印到输出.然而,与第一段代码不同,即使在两次输入之后它也不会停止,因为我可以继续输入.
为什么我可以在第二段代码中连续输入字符序列而不是第一段呢?
首先,"按Enter"对IOStreams没有特殊意义,除了\n在输入序列中输入换行符(注意,当使用文本流时,平台特定的行序列末尾被转换为单个换行符).在控制台上输入数据时,数据通常由控制台进行行缓冲,并且只有在按Enter键时才会转发到程序(通常可以关闭此项,但具体情况与平台无关并且无论如何都与此问题无关).
通过这种方式,让我们将注意力转向s.get(buffer, n)a std::istream s和指向至少n字符数组的指针的行为buffer.对此做的描述非常简单:它调用s.get(buffer, n, s.widen('\n')).由于我们正在谈论std::istream的,你可能没有改变std::locale,我们可以假设s.widen('\n')刚刚返回'\n',即调用等效于s.get(buffer, n, '\n')这里'\n'被称为分隔符,问题就变成了这个函数所做的事情.
好吧,这个函数最多可以提取m = 0 < n? n - 1: 0字符,当m到达时或者下一个字符与流中剩余的分隔符相同时停止(std::istream::getline()如果你想要提取分隔符,则使用它).任何提取的字符都存储在相应的位置中buffer,如果0 < n空字符存储在位置中buffer[n - 1].如果没有提取字符,std::ios_base::failbit则设置.
好吧,有了这个,我们应该把所有成分都放到谜语中:当你输入至少一个字符但少于5个字符时,第一次调用get()成功并将换行符留在缓冲区中作为下一个字符.下一次尝试get()更多字符立即找到分隔符,没有存储任何字符,并通过设置指示失败std::ios_base::failbit.很容易验证这个理论:
#include <iostream>
int main()
{
char buffer[5];
for (int count(0); std::cin; ++count) {
if (std::cin.get(buffer, 5)) {
std::cout << "get[" << count << "]='" << buffer << "'\n";
}
else {
std::cout << "get[" << count << "] failed\n";
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您没有输入任何字符,则第一次调用将std::cin.get()失败.如果输入1到4个字符,则第一个调用成功,但第二个调用失败.如果输入的字符数超过4个,则第二个调用也会成功,等等.有几种方法可以处理可能卡住的换行符:
std::istream::getline()与行为相同std::istream::get()但也提取分隔符,如果这是它停止阅读的原因.然而,这可能将一行切成多个读数,这可能是也可能不是所希望的.std::getline()与std::string(即std::getline(std::cin, string))一起使用.get()您可以检查下一个字符是否为换行符std::istream::peek(),std::istream::ignore()并在必要时使用.哪种方法满足您的需求取决于您要实现的目标.
| 归档时间: |
|
| 查看次数: |
3492 次 |
| 最近记录: |