class Person {
private:
string firstName;
string lastName;
public:
Person() {}
Person(ifstream &fin) {
fin >> firstName >> lastName;
}
void print() {
cout << firstName
<< " "
<< lastName
<< endl;
}
};
int main() {
vector<Person> v;
ifstream fin("people.txt");
while (true) {
Person p(fin);
if (fin == NULL) { break; }
v.push_back(p);
}
for (size_t i = 0; i < v.size(); i++) {
v[i].print();
}
fin.close();
return 0;
}
Please can you explain me, how following code snippet works? if (fin == NULL) { break; }
fin is a object on stack, not a pointer so it can not become NULL. I was unable to find overloaded operator== function in ifstream class. So I can not understand how this snippet works.
Opening a File Either ofstream or fstream object may be used to open a file for writing. And ifstream object is used to open a file for reading purpose only. Following is the standard syntax for open() function, which is a member of fstream, ifstream, and ofstream objects.
You can read information from files into your C++ program. This is possible using stream extraction operator (>>). You use the operator in the same way you use it to read user input from the keyboard. However, instead of using the cin object, you use the ifstream/ fstream object.
An ifstream is an input file stream, i.e. a stream of data used for reading input from a file. Because an ifstream IS an istream, anything you can do to an istream you can also do the same way to an ifstream.
The ifstream
class has an operator void *()
(or operator bool()
in C++11). This is what is called when you test (fin == NULL)
.
Testing fin == NULL
should be exactly the same as testing fin.fail()
.
The base classes of istream
and ostream
have implicit conversion
functions, which allow them to be used as a boolean value; in pre-C++11,
the implicit conversion was to void*
.
It was never the intent that the result of this conversion be used as a
pointer, and code like fin == NULL
shows an extremely poor
understanding of C++ and the standard streams. The idiomatic way of
writing the first loop would be to define a default constructor and an
operator>>
for Person
, and then write:
Person p;
while ( fin >> p ) {
v.push_back( p );
}
(And while I'm at it: you really should test the return value of
fin.close()
, and not return 0
if it fails:
fin.close();
return fin ? EXIT_SUCCESS : EXIT_FAILURE;
.)
This isn’t how streams are supposed to be used. True, this (unfortunately!) compiles and even does the “right” thing. But don’t write code like this. Whoever wrote this code probably thought they were clever.
But what they really did was break the expectations of C++ programmers by introducing a new, unconventional API, with no real advantages.
This code initialises an object of type Person
from an input stream. Unfortunately, by doing this, the code forgoes the opportunity to test for errors while reading the object. This isn’t good. An object should not have a constructor accepting an input stream, it should overload operator>>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With