2

I am trying to read several integers until hit eof(ctrl+d), and then read some other integers, but cin does not work anymore.

#include <iostream>
using namespace std;
int main()
{
    int c;
    while(cin >> c)
        cout << c << endl;
    int b;
    cin.clear();
    cin.ignore();
    cin >> b;
    cout<< "bla" << b << "ss" << endl; 
}

the output:(after enter "2", i hit ctrl+D)

:! ./test
1
1
2
2
bla32767ss

How to fix this?

Benjamin Bannier
  • 55,163
  • 11
  • 60
  • 80
Kevin Ling
  • 77
  • 1
  • 5

1 Answers1

1

Ctrl-D makes the standard input report EOF but leaves the file open. You can reuse std::cin after EOF, as the following simple program demonstrates:

#include <iostream>
#include <string>

int main()
{
    for (;;)
    {
        for (std::string s; std::cin >> s; )
        {
            std::cout << "Got token: " << s << "\n";
        }
        std::cin.clear();
        std::cout << "Received EOF\n";
    }
}

Now, when parsing integers, there's the possibility of a parsing error. In that case, the stream is not EOF, but in "fail" state. You also need to clear the error, but you also need to discard the unparseable values. For that you need ignore:

#include <iostream>
#include <limits>

int main()
{
    for (;;)
    {
        for (int n; std::cin >> n; )
        {
            std::cout << "Got integer: " << n << "\n";
        }
        if (std::cin.eof())
        {
            std::cout << "Received EOF\n";
            std::cin.clear();
        }
        else
        {
            std::cout << "Parsing failure\n";
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
    }
}

Your error in using ignore was twofold: You were only ignoring one character, even though the input could conceivably consist of more than one unparseable character, and you were ignoring up to EOF, rather than up to the next newline: That's because ignore() has default arguments, and ignore() is the same as ignore(1, EOF).

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • but cin.clear() doesn't work with EOF in this case.It can handle other invalid input – Kevin Ling Apr 23 '15 at 09:14
  • 1
    This will not work on TTY/PTY (e.g. Linux). A [system level pipe](https://stackoverflow.com/a/20815546/1054324) will be closed and the ICANON flag set. EOF is important concept but I think books shouldn't teach it as a way of interactive terminal control. For example the C++ Primer teaches it but doesn't tell how to recover properly. – Peter Nov 13 '22 at 14:19