I am a student of C++. I am working through the book, "Starting Out With C++ Early Objects (9th Edition). Example 27 from Chapter 6 (on Functions) reads data from a file but will not compile. Here is the full code:
// Program 6-27
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
using namespace std;
// Function prototype
bool readData(ifstream &someFile, string &city, double &rain);
int main()
{
ifstream inputFile;
string city;
double inchesOfRain;
// Display table headings
cout << "July Rainfall Totals for Selected Cities \n\n";
cout << " City Inches \n";
cout << "_________________ \n";
// Open the data file
inputFile.open("rainfall.dat");
if (inputFile.fail())
cout << "Error opening data file.\n";
else
{
// Call the readData function
// Execute the loop as long as it found and read data
while (readData(inputFile, city, inchesOfRain) == true)
{
cout << setw(11) << left << city;
cout << fixed << showpoint << setprecision(2)
<< inchesOfRain << endl;
}
inputFile.close();
}
return 0;
}
bool readData(ifstream &someFile, string &city, double &rain)
{
bool foundData = someFile >> city >> rain;
return foundData;
}
And here's the accompanying data for the data file Rainfall.dat:
Chicago 3.70
Tampa 6.49
Houston 3.80
The problem lies with this line in the "bool readData" function:
bool foundData = someFile >> city >> rain;
I am using Visual Studio Community 2017. "someFile" gets a red squiggly line and the dropdown displays the following error:
no suitable conversion function from "
std::basic_istream<char, std::char_traits<char>>
" to "bool
" exists
I don't really understand the error message but have managed to get this program working with:
A simple cast:
bool readData(ifstream &someFile, string &city, double &rain)
{
return static_cast<bool>(someFile >> city >> rain);
}
Or this as an alternative:
bool readData(ifstream &someFile, string &city, double &rain)
{
if(someFile >> city >> rain)
return true;
else
return false;
}
So, my real questions are:
The stream has a member
explicit operator bool() const;
which makes it convertible to a bool
value, but because the operator is explicit
this only works in a context that requires a bool.
You have already discovered that this includes if-statements and explicit casts. It doesn't include other types of expressions, like assignments.
Originally (C++98) the operator wasn't explicit
(because such things weren't invented yet) so the code example would probably have worked at the time. Seems like the book hasn't been updated in this part.
I'd consider
returning std::ios&
to postpone the contextual conversion to bool
std::ios& readData(std::ifstream &someFile, std::string &city, double &rain) {
return someFile >> city >> rain;
}
The upshot is that you can simple use it like so down-the-road:
if (readData(file, city, rain)) {
// ...
}
The interface will compile with just including #include <iosfwd>
manually triggering the contextual conversion:
bool readData(std::ifstream &someFile, std::string &city, double &rain) {
return bool{someFile >> city >> rain};
}
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