istream和cin.get() [英] istream and cin.get()

查看:199
本文介绍了istream和cin.get()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于这两段代码之间的区别的问题:

  char buffer5 [5] 
cin.get(buffer5,5);
cout<< buffer5;

cin.get(buffer5,5);
cout<< buffer5;

  char buffer4; 
while(cin.get(buffer4))
{
cout<缓冲区4;
}

在第一段代码中,代码获得5个字符,缓冲区5。但是,由于您按Enter键,因此在调用get()时,换行符不会被放入流中,因此程序将终止,并且不会再请求您再输入5个字符。



在第二段代码中,cin.get()等待输入流的输入,因此循环不会终止(我认为)。假设我输入苹果到输入流。这将把5个字符放入输入流,并且循环将所有字符打印到输出。但是,与第一段代码不同,它不会停止,即使在两个输入之后,我仍然可以继续输入。



为什么我可以连续输入字符序列第二段代码而不是第一段?

解决方案

首先,按Enter没有特殊意义到IOStreams,除了在输入序列中输入换行符( \\\
)(注意,当使用文本流时,平台特定的行结束序列被转换为单个换行符字符)。当在控制台上输入数据时,数据通常由控制台进行行缓冲,并且只有在按下enter时才转发到程序(通常可以关闭,但其细节是平台特定的,并且与此问题无关) p>

通过这种方式,我们可以将注意力集中到 s.get(buffer,n) std :: istream s 和指向至少 n 字符的数组的指针 / code>。这样做的描述是微不足道的:它调用 s.get(buffer,n,s.widen('\\\
'))
。因为我们在谈论 std :: istream ,你可能没有改变 std :: locale ,我们可以假设 s.widen('\\\
')
只是返回'\\\
'
,即调用相当于 s.get(buffer,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<< ] ='<<缓冲液< '\\\
;
}
else {
std :: cout< get [< count<< ] failed\\\
;
}
}
}

第一次调用 std :: cin.get()失败。如果输入1到4个字符,则第一个调用成功,但第二个调用失败。如果输入超过4个字符,第二个调用也会成功等。有几种方法可以处理可能卡住的换行符:


  1. 只需使用 std :: istream :: get()的行为相同的 std :: istream :: getline c>,但也提取分隔符,如果这是为什么它停止阅读。

  2. 为避免固定行长度的限制,您可以使用 std :: getline() std :: string (即 std :: getline(std :: cin ,string))。

  3. 成功执行 get()使用 std :: istream :: peek() std :: istream :: ignore()必要。

以下哪种方法能满足您的需求取决于您尝试达成的目标。


I have a question about the difference between these two pieces of code:

char buffer5[5];
cin.get(buffer5, 5);
cout << buffer5;

cin.get(buffer5, 5);
cout << buffer5;

and

char buffer4;
while (cin.get(buffer4))
{
    cout << buffer4;
}

In the first piece of code, the code gets 5 characters and puts it in buffer5. However, because you press enter, a newline character isn't put into the stream when calling get(), so the program will terminate and will not ask you for another round of 5 characters.

In the second piece of code, cin.get() waits for input to the input stream, so the loop doesn't just terminate (I think). Lets say I input "Apple" into the input stream. This will put 5 characters into the input stream, and the loop will print all characters to the output. However, unlike the first piece of code, it does not stop, even after two inputs as I can continuously keep inputting.

Why is it that I can continuously input character sequences into the terminal in the second piece of code and not the first?

解决方案

First off, "pressing enter" has no special meaning to the IOStreams beyond entering a newline character (\n) into the input sequence (note, when using text streams the platform specific end of line sequences are transformed into a single newline character). When entering data on a console, the data is normally line buffered by the console and only forwarded to the program when pressing enter (typically this can be turned off but the details of this are platform specific and irrelevant to this question anyway).

With this out of the way lets turn our attention to the behavior of s.get(buffer, n) for an std::istream s and a pointer to an array of at least n characters buffer. The description of what this does is quite trivial: it calls s.get(buffer, n, s.widen('\n')). Since we are talking about std::istream and you probably haven't changed the std::locale we can assume that s.widen('\n') just returns '\n', i.e., the call is equivalent to s.get(buffer, n, '\n') where '\n' is called a delimiter and the question becomes what this function does.

Well, this function extracts up to m = 0 < n? n - 1: 0 characters, stopping when either m is reached or when the next character is identical to the delimiter which is left in the stream (you'd used std::istream::getline() if you'd wanted the delimiter to be extracted). Any extracted character is stored in the corresponding location of buffer and if 0 < n a null character is stored into location buffer[n - 1]. In case, if no character is extracted std::ios_base::failbit is set.

OK, with this we should have all ingredients to the riddle in place: When you entered at least one character but less than 5 characters the first call to get() succeeded and left the newline character as next character in the buffer. The next attempt to get() more characters immediately found the delimiter, stored no character, and indicated failure by setting std::ios_base::failbit. It is easy to verify this theory:

#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";
        }
    }
}

If you enter no character, the first call to std::cin.get() fails. If you enter 1 to 4 characters, the first call succeeds but the second one fails. If you enter more than 4 characters, the second call also succeeds, etc. There are several ways to deal with the potentially stuck newline character:

  1. Just use std::istream::getline() which behaves the same as std::istream::get() but also extracts the delimiter if this is why it stopped reading. This may chop one line into multiple reads, however, which may or may not be desired.
  2. To avoid the limitation of a fixed line length, you could use std::getline() together with an std::string (i.e., std::getline(std::cin, string)).
  3. After a successful get() you could check if the next character is a newline using std::istream::peek() and std::istream::ignore() it when necessary.

Which of these approaches meets your needs depends on what you are trying to achieve.

这篇关于istream和cin.get()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆