Chapter 9 explained how you can use functions to make your code more modular. In that spirit, lets rewrite the previous program to add two functions, each to be called from main: writeFile to open a file for writing using an ofstream object, and readFile to open a file for reading using an ifstream object. Each function includes code to check if the file was opened successfully and returns a Boolean value indicating whether the file was opened successfully:
#include <fstream> #include <iostream> #include <string> using namespace std; bool writeFile (ofstream&, char*); bool readFile (ifstream&, char*); int main () { string data; bool status; ofstream outfile; status = writeFile(outfile, "students.dat"); if (!status) { cout << "File could not be opened for writing\n"; cout << "Program terminating\n"; return 0; } else { cout << "Writing to the file" << endl; cout << "===================" << endl; cout << "Enter class name: "; getline(cin, data); outfile << data<< endl; cout << "Enter number of students: "; cin >> data; cin.ignore(); outfile << data<< endl; outfile.close(); } ifstream infile; status = readFile(infile, "students.dat"); if (!status) { cout << "File could not be opened for reading\n"; cout << "Program terminating\n"; return 0; } else { cout << "Reading from the file" << endl; cout << "=====================" << endl; getline(infile, data); while(!infile.fail()) { cout << data << endl; getline(infile, data); } infile.close(); } return 0; } bool writeFile (ofstream& file, char* strFile) { file.open(strFile); if (file.fail()) return false; else return true; } bool readFile (ifstream& ifile, char* strFile) { ifile.open(strFile); if (ifile.fail()) return false; else return true; }
For each function, the file stream object is passed by reference instead of by value even though neither function changes the contents of the file. The reason is that the internal state of a file stream object may change with an open operation even if the contents of the file may not change.