Weird fstream state after open()

Hi, there,
I've done a simple code to read a file from the disk. The user must enter the filename and my program tells her if there is a problem openning the file, and if so, give her another chance. So, this is the code
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
28
int main()
{
   char keep_asking = 'y';
   fstream data_file;
   string  data_file_name;
   
   do
   {
      cout << "Enter file name: ";
      cin >> data_file_name;
        
      int value_1 = 0, value_2 = 0;
      
      data_file.open (data_file_name.c_str ());
      if (data_file.is_open ())
      {
         data_file >> value_1 >> value_2;
         
         data_file.close ();
         keep_asking = 'n';
      } 
      else
         keep_asking = 'y';
   }while (keep_asking == 'y');  

   cout << "\nValue_1 = " << value_1 << "\nValue_2 = " << value_2 << "\n";
   cout << "End of program." << endl;
   return 0;

OK, you can try this and enter a correct file name, everything is fine. Next test, enter a wrong name. As long as there is no file with this name, you are asked to enter a new one. This time you enter the right one, OK, the file is opened BUT the data are not read from the file. This happenes regardless the number of times a wrong name is entered.

If you put delcaration of the fstream "data_file" (and the string associated) inside the do-while loop, everything works as expected. This makes sense, as long as the fstream is freshly created in every loop, but the question is what is happening to the fstream object in the first version?.

It looks like trying to open a fstream object with the wrong name, doesn't leave it as if it was brand new, so in the next loop (with a correct name) it's not possible to read data inside.

Does any one knows what happens?

Thanks in advance.

It would be better not to reuse an fstream object. Even close() can set the failbit. If you must reuse you will want to check data_file.good() and if any of the failbits are set call clear() before you open a new file with the fstream instance.

For Example:
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
28
29
int main()
{
   char keep_asking = 'y';
   fstream data_file;
   string  data_file_name;
   
   do
   {
      data_file.clear();
      cout << "Enter file name: ";
      cin >> data_file_name;
        
      int value_1 = 0, value_2 = 0;
      
      data_file.open (data_file_name.c_str ());
      if (data_file.is_open ())
      {
         data_file >> value_1 >> value_2;
         
         data_file.close ();
         keep_asking = 'n';
      } 
      else
         keep_asking = 'y';
   }while (keep_asking == 'y');  

   cout << "\nValue_1 = " << value_1 << "\nValue_2 = " << value_2 << "\n";
   cout << "End of program." << endl;
   return 0;
Last edited on
First of all, thank you for your help, Texan.

You're right. Your code works fine. It's a good example of defensive coding. I still feel courious about what happens to the object data_file when someone tries to open it with a wrong name.
Some fields of the class keep track of the essay, and that makes subsequent calls to is_open () answer everything is OK, when there is not.

On the other hand, I tried my code on a linux box and there, my firstly reported problem doesn't shows up, what makes me think this an implementation issue. Could I be right?

Anyway, I'll use data_file.clear () always in this kind of situations.

Regards and thanks again.

Fernando
thank you for your help. i need this too.
Topic archived. No new replies allowed.