papagaga
papagaga

Reputation: 1158

why istream::get sets failbit and eofbit together?

I wonder why istream::get sets failbit and eofbit together.

The behaviour of std::getline is different: it sets eofbit when it encounters the end of the file, and failbit when you try to read past the end of the file. So you can write:

while (std::getline(is, s) {
  blablabla... // gets executed once after end of file has been reached
}

whereas if you define your own getSthg function with std::get

std::istream& myOwnGetLine(std::istream& is, std::string& s) {
  char c;
  while (is.get(c)) {
    blablabla...
  }
  return is;
}

then:

while (myOwnGetLine(is, s)) { // fails if eof has been reached
  blablabla // won't get executed for the last line of the stream
}

So: what am I doing wrong? The work-around I came up with is:

std::istream& myOwnGetLine(std::istream& is, std::string& s) {
  *if (is.rdstate() & std::ios::eofbit) { 
    is.clear(std::ios::failbit);
    return is;
  }*  
  char c;
  while (is.get(c)) {
    blablabla...
  }
  *if (is.rdstate() & std::ios::eofbit) {
    is.clear(std::ios::eofbit);
  }*
  return is;
}

but that doesn't sound right...

Upvotes: 1

Views: 433

Answers (1)

Mats Petersson
Mats Petersson

Reputation: 129364

Unfortunately, using istream::get to make a getline function will lead to some awkward code inside that function, since as per specification, it sets both eofbit and failbit when it reeaches end-of-file. The way the standard istream::getline solves this problem is by using the rdbuf() of the istream to inspect values. And it looks like that is probably the only way to solve this problem (aside from manipulating the failure state of the stream, that is)

Upvotes: 2

Related Questions