Here is a C++ code which reads as many words
from a given text file as possible until it meets EOF.
string text;
fstream inputStream;
inputStream.open("filename.txt");
while (inputStream >> text)
cout << text << endl;
inputStream.close();
My question is:
what procedure exactly is performed behind on converting the condition of the while loop (i.e., inputStream >> text) into a boolean values (i.e., true or false)?
My own answer for the question is:
To my understanding, inputStream >> text is supposed to return another (file) input stream. The stream seems to be NULL when EOF arrives. The NULL may be defined as 0, which is equivalent to false.
Does my answer make sense? Even if my answer does make sense, such conversion of InputStream to bool doesn't make me so comfortable. :)
what procedure exactly is performed behind on converting the condition of the while loop (i.e., inputStream >> text) into a boolean values (i.e., true or false)?
operator>> returns a reference to the stream.
In C++11 the reference is then converted to a bool by the stream's operator bool() function, which returns the equivalent of !fail().
In C++98 the same is achieved by using operator void*(), and the returned pointer is either NULL to indicate failure or a non-null pointer if fail() is false, which is then implicitly converted to a bool in the while evaluation.
I know that my answer has been perfectly answered by user657267. But I am adding one more example to understand the answer more easily.
// evaluating a stream
#include <iostream> // std::cerr
#include <fstream> // std::ifstream
int main () {
std::ifstream is;
is.open ("test.txt");
if (is) { <===== Here, an example of converting ifstream into bool
// read file
}
else {
std::cerr << "Error opening 'test.txt'\n";
}
return 0;
}
Ref. http://www.cplusplus.com/reference/ios/ios/operator_bool/
Related
When I use an std::istream object (in the example below from cplusplus.com, an std::ifstream) in a test : "if (myistreamobject)", the object, which is automatically allocated in the stack is never null, right ?... in the example below, we are using the same test to check if all the bytes were read from the file... and that's really a strange code, I usually use that style when I'm dealing with pointers...
I want to know which mechanism is used in std::istream to return a value in tests, and what that value really means... (the success/failure of the last operation ??) is it an overloading of a bool cast (like the const char* operator cast in the MFC class CString) or it is another technique ?
Because the object is never null, so putting it in a test will always return true.
// read a file into memory
#include <iostream> // std::cout
#include <fstream> // std::ifstream
int main () {
std::ifstream is ("test.txt", std::ifstream::binary);
if (is) {
// get length of file:
is.seekg (0, is.end);
int length = is.tellg();
is.seekg (0, is.beg);
char * buffer = new char [length];
std::cout << "Reading " << length << " characters... ";
// read data as a block:
is.read (buffer,length);
if (is) // <== this is really odd
std::cout << "all characters read successfully.";
else
std::cout << "error: only " << is.gcount() << " could be read";
is.close();
// ...buffer contains the entire file...
delete[] buffer;
}
return 0;
}
if (expression)
tests it expression evaluates to true which is a boolean. It works for pointers because nullptr/NULL/0 evaluate to false, and everything else true. It works for integral values for the same reason.
For an object, it falls to operator bool(), see http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool.
Checks whether the stream has no errors.
1) Returns a null pointer if fail() returns true, otherwise returns a non-null pointer. This pointer is implicitly convertible to bool and may be used in boolean contexts.
2) Returns true if the stream has no errors and is ready for I/O operations. Specifically, returns !fail().
This operator makes it possible to use streams and functions that return references to streams as loop conditions, resulting in the idiomatic C++ input loops such as while(stream >> value) {...} or while(getline(stream, string)){...}.
Such loops execute the loop's body only if the input operation succeeded.
The
operator bool()
returns true if the stream has no errors, false otherwise.
The "no error" concept is something related with the previous operation done on the stream itself.
For example: after you invoke the constructor
std::ifstream is ("test.txt", std::ifstream::binary);
A internal status flag in the stream object is set. So when you invoke the operator bool you check whether the construction operation fails or not.
Moreover the method
is.read(...)
also set this internal status flag, as you can see in the reference:
Errors are signaled by modifying the internal state flags: eofbit, failbit, badbit.
So after the method call, if the stream reaches the EOF (end-of-file) the state bit is set, and the operator bool will return a positive value.
That means in that case when you test the stream with
if (is) { ... }
and the status bit is set, then the condition will be verified and the if-branch will be taken.
std::istream has operator declared right this:
explicit operator bool() const;
When you write
if(SomeStdIstremObject) { ... } really is calling if(SomeStdIstreamObject.operator bool()) not checking for non zero
I've used statements such as this quite a bit in my C++ programming:
std::string s;
std::ifstream in("my_input.txt");
if(!in) {
std::cerr << "File not opened" << std::endl;
exit(1);
}
while(in >> s) {
// Do something with s
}
What I want to know is, why does this work?
I looked at the return value of operator>>, and it's an istream object, not a boolean. How does an istream object somehow get interpreted as a bool value that can be put inside of if statements and while loops?
The base class std::basic_ios provides an operator bool() method that returns a boolean representing the validity of the stream. For example, if a read reached the end of file without grabbing any characters, then std::ios_base::failbit will be set in the stream. Then operator bool() will be invoked, returning !fail(), at which time extraction will stop because the condition is false.
A conditional expression represents an explicit boolean conversion, so this:
while (in >> s)
is equivalent to this
while (static_cast<bool>(in >> s))
which is equivalent to this
while ((in >> s).operator bool())
which is equivalent to
while (!(in >> s).fail())
std::basic_ios, from which the input and output streams inherit, has the conversion function operator bool (or operator void* prior to C++11 to get around the safe-bool problem, which is no longer an issue thanks to the explicit keyword).
See std::basic_ios::operator bool:
This operator makes it possible to use streams and functions that return references to streams as loop conditions, resulting in the idiomatic C++ input loops such as while(stream >> value) {...} or while(getline(stream, string)){...}. Such loops execute the loop's body only if the input operation succeeded.
I recently used fstream for a homework assignment and I was wondering about how two things worked.
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char** argv) {
ifstream myFile;
myFile.open("fileone.txt");
int myInt = 0;
while (myFile.good()) { // What is the difference between myFile and myFile.good()?
if (!myFile.eof()){
myFile >> myInt;
cout << myInt << endl;
}
}
return 0;
}
This is a snippet of my actual code I am working on. In another post, someone said that if I used while(myFile) , it would automatically convert into a bool. What is the difference between using this and using the member function .good() of the ifstream class? I know that .good() breaks out of the while loop when I reach the end of the text file but how does using the stream name behave?
IOStream classes have 4 functions for assessing the stream state: good(), bad(), fail(), and eof(). Excluding good(), each function checks a single bit in the underlying stream state and returns whether or not the bit is on (are there errors?). good() in particular checks if all the bits are off (is the stream valid?). These are what they are for:
good(): The stream has not encountered an error.
bad(): The stream has encountered an error that effects the integrity of the stream (i.e memory allocation failure, no buffer, etc.)
fail(): Typically a recoverable error (formatting/parsing failure).
eof(): The end-of-file (EOF) character has been reached.
When performing I/O, it is integral that you check for errors in the stream while processing input. What novices typically don't know is that the only function that was meant to be used to check for valid input is fail(). All the other functions are useful in other cases but not for conditioning input.
Futhermore, novices also fail to realize that input must be performed before checking for errors. Doing otherwise allows an unchecked extraction, allowing the body of the loop to access the value that was not produced from a valid extraction.
Streams have a boolean operator that returns !fail(), this allows you to check the stream in an elegant way after performing input, like this:
while (myFile >> myInt) {
// ...
}
This is the best way to perform input. The extraction itself should be present within a conditional context so that the body of whatever its being used in is executed only if the extraction succeeded.
Read the manual.
The bool conversion is defined so that the following are the same:
if (stream) { ... }
if (!stream.fail()) { ... }
There is a difference between stream.good() and !stream.fail(): !fail is also true the end of file.
And one more big issue with your code: you should check if the read is successful before using the input. So this is really bad:
myFile >> myInt;
cout << myInt << endl
because you have not checked if you really succeeded to read an int into myInt.
TLDR:
Use this for reading ints from a file:
while (myFile >> myInt) {
cout << myInt << endl;
}
Reason: myFile >> myInt returns myFile so it will invoke the bool conversion which should be used as the loop condition.
I'm reading file by file stream in the C++ Standard Library:
std::ifstream infile(path.c_str());
if (!infile.is_open())
{
return -1;
}
std::string line;
while (std::getline(infile, line))
{
std::cout << line << std::endl;
}
This works. What impressed me is that std::getline actually returns an std::ifstream&; how can a reference to object work as a boolean expression? Second, if I write it this way:
while (NULL != std::getline(infile, line))
this also works. I don't get it why a reference here works like a pointer.
It's not the object reference: std::ifstream supports conversion to bool (it used to be void* before C++11), as you can see here: http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool.
It returns true (a non null pointer before C++11) unless the stream is in error or at EOF.
std::ifstream is convertible to boolean. Specifically, it's true if the stream is good, and false if the stream is bad or fail.
std::ifstream defines void * conversion operator. So you can compare the reference with a pointer and as a boolean condition.
Quoting about the return value of this conversion operator from cplusplus.com
Return Value: A null pointer if at least one of failbit or badbit is set. Some other
value otherwise
I find myself repeatedly baffled by the rdstate() flags - good(), bad(), eof(), fail() - and how they are expressed in basic_ios::operator!, operator bool and operator void*.
Could somebody put me out of my misery and explain this so I never have to think twice again?
There are three flags that indicate error state:
badbit means something has gone very wrong with the stream. It might be a buffer error or an error in whatever is feeding data to the stream. If this flag is set, it's likely that you aren't going to be using the stream anymore.
failbit means that an extraction or a read from the stream failed (or a write or insertion for output streams) and you need to be aware of that failure.
eofbit means the input stream has reached its end and there is nothing left to read. Note that this is set only after you attempt to read from an input stream that has reached its end (that is, it is set when an error occurs because you try to read data that isn't there).
The failbit may also be set by many operations that reach EOF. For example, if there is only whitespace left remaining in the stream and you try to read an int, you will both reach EOF and you will fail to read the int, so both flags will be set.
The fail() function tests badbit || failbit.
The good() function tests !(badbit || failbit || eofbit). That is, a stream is good when none of the bits are set.
You can reset the flags by using the ios::clear() member function; this allows you to set any of the error flags; by default (with no argument), it clears all three flags.
Streams do not overload operator bool(); operator void*() is used to implement a somewhat broken version of the safe bool idiom. This operator overload returns null if badbit or failbit is set, and non-null otherwise. You can use this to support the idiom of testing the success of an extraction as the condition of a loop or other control flow statement:
if (std::cin >> x) {
// extraction succeeded
}
else {
// extraction failed
}
The operator!() overload is the opposite of the operator void*(); it returns true if the badbit or failbit is set and false otherwise. The operator!() overload is not really needed anymore; it dates back to before operator overloads were supported completely and consistently (see sbi's question "Why does std::basic_ios overload the unary logical negation operator?").
C++0x fixes the problem that causes us to have to use the safe bool idiom, so in C++0x the basic_ios base class template does overload operator bool() as an explicit conversion operator; this operator has the same semantics as the current operator void*().
In addition to James' answer, it's important to remember that these flags indicate results of operations, so won't be set unless you perform one.
A common error is to do this:
#include <fstream>
#include <iostream>
#include <string>
int main()
{
std::ifstream file("main.cpp");
while (!file.eof()) // while the file isn't at eof...
{
std::string line;
std::getline(file, line); // ...read a line...
std::cout << "> " << line << std::endl; // and print it
}
}
The problem here is that eof() won't be set until after we try to get the last line, at which point the stream will say "nope, no more!" and set it. This means the "correct" way is:
#include <fstream>
#include <iostream>
#include <string>
int main()
{
std::ifstream file("main.cpp");
for (;;)
{
std::string line;
std::getline(file, line); // read a line...
if (file.eof()) // ...and check if it we were at eof
break;
std::cout << "> " << line << std::endl;
}
}
This places the check in the correct location. This is very unruly though; luckily for us, the return value for std::getline is the stream, and the stream has a conversion operator that allows it to be tested in a boolean context, with the value of fail(), which includes eof(). So we can just write:
#include <fstream>
#include <iostream>
#include <string>
int main()
{
std::ifstream file("main.cpp");
std::string line;
while (std::getline(file, line)) // get line, test if it was eof
std::cout << "> " << line << std::endl;
}