problem with good() member function in ifstream

I wrote a list of code which try to read in digits from a text file. And I wanna stop the loop if up to the EOF of the file.
It comes to me a problem that .good() function doesn't work like what I thought. I wish I could get help from friends here :)

1
2
3
4
5
6
7
8
9
// To make it clear, I show here the core code

vector<int> arr;
int temp;
filein >> temp;
while (filein.good()){
	arr.push_back(temp);
	filein >> temp;
}

I can't read the last digit in my text file. But I substituted the while (filein.good()) with while (filein), the last digit be read.

And if I press Enter key at the end of the text file, .good() works as well.

I wanna know why .good() wrong. Thx.

Last edited on
> I substituted the while (filein.good()) with while (filein), the last digit be read.

If the file does not contain any character after the last number, the file would be in an eof state (not good) after the last number is read.

Write the loop this way; this is canonical:
1
2
3
4
5
std::vector<int> arr;

int temp;

while( filein >> temp ) arr.push_back(temp);
The correct way to input data from C++ streams is to use the input operation as the condition.

Your code would then look like this:

1
2
3
4
5
6
vector<int> arr;
int temp;

while (filein >> temp){
	arr.push_back(temp);
}


lays wrote:
I wanna know why .good() wrong. Thx.

It is wrong to use filein.good() as the condition because it checks the current state of the stream, but what you really wanted is to check if the input operation was successful.

For the same reason it is wrong to use filein itself as the condition (it still checks the current state of the stream).

http://www.cplusplus.com/reference/ios/ios/good/
http://www.cplusplus.com/reference/ios/ios/operator_bool/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// wrong method #1
while (filein.good()) // check: eofbit, failbit, badbit
{
    // do input (what if it fails?)
}

// wrong method #2
while (filein) // check: failbit, badbit
{
    // do input (what if it fails?)
}

// good method
while (/* do input */) // check: failbit, badbit right after input
{
    // if the input fails above, the loop body won't be entered
}

> For the same reason it is wrong to use filein itself as the condition
> (it still checks the current state of the stream).

There is a significant difference between if( stm.good() ) and if(stm)
This is verbose, but it is fine:

1
2
3
4
5
6
7
vector<int> arr;
int temp;
filein >> temp;
while(filein){
	arr.push_back(temp);
	filein >> temp;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <sstream>

void show_results( std::ios& stm )
{
    std::cout << std::boolalpha << "bad: " << stm.bad() << "   fail: " << stm.fail()
               << "   eof: " << stm.eof() << "   good: " << stm.good()
               << "   bool(stm): " << bool(stm) << "   !stm: " << !stm << '\n' ;
}

int main()
{
   std::istringstream stm( "123 456" ) ;
   int i ;

   stm >> i ;
   show_results( stm ) ;
   // bad: false   fail: false   eof: false   good: true   bool(stm): true   !stm: false

   stm >> i ;
   show_results( stm ) ;
   // bad: false   fail: false   eof: true   good: false   bool(stm): true   !stm: false

   stm >> i ;
   show_results( stm ) ;
   // bad: false   fail: true   eof: true   good: false   bool(stm): false   !stm: true
}

http://coliru.stacked-crooked.com/a/05d5c9cc2bc2d3c4
Thx, I know where the problem is?

But why filein as condition right? It push back the last digit.
1
2
3
4
5
6
7
vector<int> arr;
int temp;
filein >> temp;
while (filein){
	arr.push_back(temp);
	filein >> temp;
}
> But why filein as condition right?

if(filein) : true if the last input operation was successful ie. !filein.fail()

if( filein.good() ) : true if none of bad, fail, eof bits are set ie. filein.rdstate() == 0

After reading the last number (no newline at the end), the state is bad:false fail:false eof:true good:false
if(filein) : true
if( filein.good() ) : false
Last edited on
Topic archived. No new replies allowed.