2

Does calling ifstream::close reset the stream's failbit and/or badbit, similar to calling clear? This is not a duplicate of this question- I need to know whether the flags are reset, not just when they're set.

For example, I'm using something like the following if-else in my current project:

ifstream myInputStream("foo.txt");

//Let's pretend this compiles all the time, even though it
//might not because the operator is ambiguous.
myInputStream << "Outputting to an input stream causes problems."

if (myInputStream.fail())
{
   cout << "Aw, nuts. It failed." << endl;
   myInputStream.close();
   return false;
}
else
{
   cout << "No nuts here. Only chocolate chips." << endl;
   myInputStream.close();
   return true;
}

Do I have to have the call to myInputStream.close after the call to myInputStream.fail, in each branch, to get an accurate check? Or will this work:

ifstream myInputStream("foo.txt");

myInputStream << "Outputting to an input stream causes problems.";    

myInputStream.close();

if (myInputStream.fail())
{
   cout << "Aw, nuts. It failed." << endl;
   return false;
}
else
{
   cout << "No nuts here. Only chocolate chips." << endl;
   return true;
}

I know that ifstream::close can itself set failbit or badbit if closing fails, which is one reason I want to call it before checking for failure- I need to return false regardless of what caused it. It also looks less cluttered if the closure is only done once.

tl;dr;

Does ifstream::close reset failbit or badbit if something else has already set it, making my second code sample return true?

Community
  • 1
  • 1
Michael Hoffmann
  • 2,411
  • 2
  • 24
  • 42
  • _"Do I have to have the call to myInputStream.close after the call to myInputStream.fail, in each branch, to get an accurate check?"_ Why do you need to call `close()` at all? Closing an `fstream` _can_ fail, but most programs don't need to check for it failing, so can just let the destructor close the file. Why do you care if closing an _input_ stream fails? You don't have to worry about any pending writes being flushed to the file if it's an input stream. – Jonathan Wakely Sep 29 '15 at 00:17
  • http://en.cppreference.com/w/cpp/io/basic_ifstream/close – Jonathan Wakely Sep 29 '15 at 00:22
  • I need to call `close()` because the file might need to be opened again fro reading or for writing before the object is guaranteed to be destructed, depending on user input. I could refactor to avoid this, but using `close()` after the file's read is also a requirement for my class. I guess that's mostly why I need to use it :P – Michael Hoffmann Sep 29 '15 at 17:42
  • 1
    So you're not really doing `return true` / `return false` as in the example above? In that code calling `close()` just before the object is destroyed anyway is completely pointless. I would try to structure the code so you construct an ifstream when you need to open a file and destroy it when you're done with it, rather than keeping a long-lived object that you open/close repeatedly. – Jonathan Wakely Sep 30 '15 at 09:43
  • The code in my example is similar to what I'm actually doing, but the code is inside a function that takes a reference to an already-open ifstream, does some checking, and then sometimes closes it. I feel like this is a bad control flow, because the caller can't expect whether the stream it passes will still be open, but it's a part of the assignment. I think our professor might be having us do things in a simple way that works, even if it isn't the best, so we can improve on our own code later in the semester with more complicated concepts. That seems to be his M.O. – Michael Hoffmann Sep 30 '15 at 18:28

2 Answers2

5

close() should not clear any of the state flags, although it might set failbit depending on the return value of the underlying buffer.

[fstream.members] (also [ifstream.members] and [ofstream.members])

void close();

Effects: Calls rdbuf()->close() and, if that function returns returns a null pointer, calls setstate(failbit) (27.5.5.4) (which may throw ios_base::failure).

The flags are cleared by open() however, assuming the filebuf opens correctly

void open(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out);

Effects: Calls rdbuf()->open(s,mode). If that function does not return a null pointer calls clear(), otherwise calls setstate(failbit), (which may throw ios_base::failure) (27.5.5.4).

user657267
  • 20,568
  • 5
  • 58
  • 77
1

Using the example code in the question (modified so it compiles with g++), it looks like ifstream::close does not reset failbit. I don't know about badbit, however (ios::fail returns true if either is set).

#include <fstream>
#include <iostream>
using namespace std;

int main()
{
   ofstream writer("foo.txt");

   writer << "These are not integers.";

   writer.close();

   ifstream myInputStream("foo.txt");

   int i;
   myInputStream >> i;//This should set the failbit.

   myInputStream.close();//Will this reset it?

   if (myInputStream.fail())
   {
      cout << "Aw, nuts. It failed." << endl;
      return false;
   }
   else
   {
      cout << "No nuts here. Only chocolate chips." << endl;
      return true;
   }
}

Output: Aw, nuts. It failed.

myInputStream.fail() is returning false.

Michael Hoffmann
  • 2,411
  • 2
  • 24
  • 42
  • 2
    Reading from a deleted file doesn't cause a problem, the file is not deleted while there is an open file handle to it. So you are not observing the state being reset, it was just always clear. – Jonathan Wakely Sep 29 '15 at 00:14