Different outputs from g++ and vc++

The following code behaves differently when compiled with g++ and with VC++ (in VS 2008):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main(int argc, char *argv[]) {
  ifstream infile;
  char *str = new char[1000];
  for (int i = 0; i < 4; i++) {
    infile.open(argv[1],ios::in);
    if (!infile.is_open()) {
      cerr<<"FoF"<<endl;
      exit(1);
    }
    while(!infile.eof()) {
      infile.getline(str,1000);
      cout<<i<<" "<<str<<endl;
    }
    infile.close()
  }
  return 0;
}


It traverses the file 4 times using g++ while just once with VC++ and one needs to add infile.seekg(ios::beg); after open() to make it traverse the file multiple times using VC++.
Can anyone tell me if this is a know issue and why does this fundamental behavior vary across compilers?
Last edited on
Please edit your post and put code tags around the source.
Perhaps the standard doesn't define what to do with the get pointer if you call close() but reuse the stream. Or maybe one of them is non standards compliant in that regard. Either way, moving the stream to its proper scope would fix it. This is your code, with indentation and some spaces added for clarity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main(int argc, char *argv[])
{
    ifstream infile;
    char *str = new char[1000];
    for (int i = 0; i < 4; i++) {
        infile.open(argv[1],ios::in);
        if (!infile.is_open()) {
            cerr << "FoF" << endl;
            exit(1);
        }
        while(!infile.eof()) {
            infile.getline(str,1000);
            cout << i << " " << str << endl;
        }
        infile.close();  // added a semicolon here
    }
return 0;
}


Now try to run this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main(int argc, char *argv[])
{
    string str;  // it's C++
    for (int i = 0; i < 4; i++) {
        ifstream infile(argv[1]);
        if (!infile.is_open()) {
            cerr << "FoF" << endl;
            exit(1);
        }
        while(getline(infile, str)) {
            cout << i << " " << str << endl;
        }
    }
return 0;
}

Notice that now you create a different ifstream object on every iteration, while allowing the destructor to flush the buffer and close the file for you.
@filipe:
"Once closed, the same file stream object may be used to open another file." -- http://www.cplusplus.com/reference/iostream/ifstream/

@filipe: Thanks for the corrections and the explanation. I knew that creating different ifstream objects will fix the problem. I was inquisitive that having closed the stream, why doesn't open() reposition the pointer in VC++ while it does in g++ and whether such issues should often be cared for while porting code across compilers.

@PanGalactic: Edited to add code tags. The ifstream reference still doesn't make it clear if the same file stream object may be used to open another file should reposition the stream pointer or not?
I dunno, because vc++ is bad and doesn't follow the standard? AFAIK the standard demands that when a file is opened, it starts from the start.
closed account (z05DSL3A)
I am uncertain if open() is meant to clear any flags on the stream or not. As a matter of course, If I reuse a stream I call clear() before hand (usually after close() )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main(int argc, char *argv[]) {
  ifstream infile;
  char *str = new char[1000];
  for (int i = 0; i < 4; i++) {
	  
    infile.open("C://test.txt",ios::in);
    if (!infile.is_open()) {
      cerr<<"FoF"<<endl;
      exit(1);
    }
    while(!infile.eof()) {
      infile.getline(str,1000);
      cout<<i<<" "<<str<<endl;
    }
    infile.close();
    infile.clear();
  }
  return 0;
}

Last edited on
C++ ('98 Standard) 27.8.1.13 part 3.
If open() fails, failbit is set. There's nothing about the stream state being changed beyond that.

So you need to call clear(). Surprisingly, Visual C++ is doing the right thing.

I have to say that in all my many many years of using C++, I have never called open on a file stream. It goes against the whole ethos of a stream in my view. I support open/close being removed from fstream.
Last edited on
+1 on removing open/close. RAII all the way. I also want decent exception semantics. Oh, and the constructor should take a friggin' std::string. (Grrr!!)
...and more surprisingly, the code does traverse the file multiple times in VC++ 2010 though probably flouts the standards, as kbw said!
Is it flouting the standards or is this behavior undefined?
closed account (z05DSL3A)
undefined.
Topic archived. No new replies allowed.