The important point is that after you’ve declared an ifstream object and associated it with a file, you can use it exactly as you would use cin. All the operations and methods available to cin are also available to ifstream objects, such as inFile and fin in the preceding examples.
What happens if you attempt to open a non-existent file for input? This error causes subsequent attempts to use the ifstream object for input to fail. The preferred way to check whether a file was opened successfully is to use the is_open() method. You can use code like this:
inFile.open("bowling.txt");
if (!inFile.is_open())
{
exit(EXIT_FAILURE);
}
The is_open() method returns true if the file was opened successfully, so the expression !inFile.is_open() is true if the attempt fails. The exit() function is prototyped in the cstdlib header file, which also defines EXIT_FAILURE as an argument value used to communicate with the operating system. The exit() function terminates the program.
The is_open() method is relatively new to C++. If your compiler doesn’t support it, you can use the older good() method instead. As Chapter 17 discusses, good() doesn’t check quite as extensively as is_open() for possible problems.
The program in Listing 6.16 opens a file specified by the user, reads numbers from the file, and reports the number of values, their sum, and their average. It’s important that you design the input loop correctly, and the following “Program Notes” section discusses this in more detail. Notice that this program benefits greatly from using if statements.
Listing 6.16. sumafile.cpp
// sumafile.cpp -- functions with an array argument
#include
#include
#include
const int SIZE = 60;
int main()
{
using namespace std;
char filename[SIZE];
ifstream inFile; // object for handling file input
cout << "Enter name of data file: ";
cin.getline(filename, SIZE);
inFile.open(filename); // associate inFile with a file
if (!inFile.is_open()) // failed to open file
{
cout << "Could not open the file " << filename << endl;
cout << "Program terminating.\n";
exit(EXIT_FAILURE);
}
double value;
double sum = 0.0;
int count = 0; // number of items read
inFile >> value; // get first value
while (inFile.good()) // while input good and not at EOF
{
++count; // one more item read
sum += value; // calculate running total
inFile >> value; // get next value
}
if (inFile.eof())
cout << "End of file reached.\n";
else if (inFile.fail())
cout << "Input terminated by data mismatch.\n";
else
cout << "Input terminated for unknown reason.\n";
if (count == 0)
cout << "No data processed.\n";
else
{
cout << "Items read: " << count << endl;
cout << "Sum: " << sum << endl;
cout << "Average: " << sum / count << endl;
}
inFile.close(); // finished with the file
return 0;
}
To use the program in Listing 6.16, you first have to create a text file that contains numbers. You can use a text editor, such as the text editor you use to write source code, to create this file. Let’s assume that the file is called scores.txt and has the following contents:
18 19 18.5 13.5 14
16 19.5 20 18 12 18.5
17.5
The program has to be able to find the file. Typically, unless your input includes a pathname with the file, the program will look in the same folder or directory that contains the executable file.
Caution
A Windows text file uses the carriage return character followed by a linefeed character to terminate a line of text. (The usual C++ text mode translates this combination to newline character when reading a file and reverses the translation when writing to a file.) Some text editors, such as the Metrowerks CodeWarrior IDE editor, don’t automatically add a this combination to the final line. Therefore, if you use such an editor, you need to press the Enter key after typing the final text and before exiting the file.
Here’s a sample run of the program in Listing 6.16:
Enter name of data file: scores.txt
End of file reached.
Items read: 12
Sum: 204.5
Average: 17.0417
Program Notes
Instead of hard-coding a filename, the program in Listing 6.16 stores a user-supplied name in the character array filename. Then the array is used as an argument to open():
inFile.open(filename);
As discussed earlier in this chapter, it’s vital to test whether the attempt to open the file succeeded. Here are a few of the things that might go wrong: The file might not exist, the file might be located in another directory or file folder, access might be denied, and the user might mistype the name or omit a file extension. Many a beginner has spent a long time trying to figure what’s wrong with a file-reading loop when the real problem was that the program didn’t open the file. Testing for file-opening failure can save you such misspent effort.