11

Possible Duplicate:
C++ can I reuse fstream to open and write multiple files?

why is it not possible to use one ifstream variable for opening one file, reading it, then closing it and, after that, opening another file, reading and closing, etc? How would that look in code (let's just say each file has an integer inside):

int k, l;  
ifstream input1;  
input1.open("File1.txt");  
input1 >> k;  
input1.close();  
input1.open("File2.txt");  
input1 >> l;  
input1.close(); 

the only way I solved the problem was creating another ifstream variable.

Community
  • 1
  • 1
psukys
  • 387
  • 2
  • 6
  • 20
  • 1
    Who says it's not possible? Is this a trick question? – Kerrek SB Nov 15 '11 at 13:31
  • have you tried calling `input1.clear();` before opening the next file? – Will Nov 15 '11 at 13:32
  • It's not a trick, I'm pretty newb with c++ When I used with my files, it apparently didn't read the second one. Does it have do something with pointers? – psukys Nov 15 '11 at 13:33
  • sorry, tried bit of searching, though didn't find that specific thread – psukys Nov 15 '11 at 13:35
  • 2
    @shookees: I suppose what I was trying to imply is that it's not a good philosophical approach to knowledge to presuppose something that is uncertain. Your question makes the assumption that it's impossible, and so you are mentally disadvantaged because you're already biased against the solution. A better way to ask about something you're unfamiliar with is "Where do I fail to understand how to do X?" – Kerrek SB Nov 15 '11 at 13:43
  • @KerrekSB +1 for teaching shookees – mloskot Nov 15 '11 at 14:12

4 Answers4

17

You can use the same variable, you need to call .clear() to clear the object's flags before you reuse it:

int k,l;
ifstream input1;  
input1.open("File1.txt");  
input1 >> k;  
input1.close();  
input1.clear();
input1.open("File2.txt");  
input1 >> l;  
input1.close();
input1.clear();

But I recommend instead you don't reuse them. If you don't want to have more than one variable around at once, you can keep each one in its own scope:

int k,l;

{
    std::ifstream input1("File1.txt");  
    input1 >> k;
}
{
    std::ifstream input1("File2.txt");  
    input1 >> l;  
}
SoapBox
  • 20,457
  • 3
  • 51
  • 87
  • 2
    From C++0X on, there is no need to call ifstream::clear() because the standard specifies (see C++0x/27.9.1.9) successful ifstream::open() shall call ifstream::clear(). – mloskot Nov 15 '11 at 16:23
5

Invoke clear() after close() on ifstream object

Bojan Komazec
  • 9,216
  • 2
  • 41
  • 51
4

The original code from the question works well:

#include <fstream>
using namespace std;
int main()
{
    int k, l;  
    ifstream input1;  
    input1.open("file1.txt");
    input1 >> k;
    input1.close();  
    input1.open("file2.txt");  
    input1 >> l;  
    input1.close(); 
}

Note, from C++0X (C++11) on, there is no need to call basic_ifstream::clear() because the standard specifies (see C++0x/27.9.1.9) successful basic_ifstream::open() shall call basic_ifstream::clear().

mloskot
  • 37,086
  • 11
  • 109
  • 136
  • I believe that the problem persists here. – psukys Nov 15 '11 at 13:43
  • 1
    @shookees Belief is not enough, I believe. This code compiles and the program runs (it even reads the two sample files). Be specific, give details, give errors. Your question is far from ideal, hardly possible to answer (so, I got -1 for criticising your incomplete question, keep fiddling). – mloskot Nov 15 '11 at 14:09
  • I'm sorry, I didn't -1 that, also seems that my compiler did not aquire the newest standard at that time. – psukys Jan 07 '15 at 11:40
  • @shookees that's OK, sorry for misinterpreting the downvote, cheers – mloskot Jan 07 '15 at 22:42
2

While it's entirely possible to do what you suggest (though you may need to clear the stream's error flags if the extraction failed), it's not terribly elegant. In C++, you should feel free to make new objects when you need them, and discard them when you're done. Perhaps a more systematic way to write this code is in a local loop scope:

int result;

while (true)
{
  std::ifstream infile(get_random_file_name());
  if (infile >> n) { break; }
  // "infile" gets destroyed at the end of the scope
}

std::cout << "We found a good file, and it contains: " << n << std::endl;

You can of course replace the loop logic by anything else that's more appropriate to your situation. For example, according to the Zero-One-Many rule, you might have a container somewhere that contains your candidate filenames; or you could be looping over command-line arguments.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084