The first solution for the Rolodex problem is based on the C++ string class. Furthermore, it's much easier to test the program as we write it rather than waiting until it's finished. If we test the program throughout development, we know that any new problems are likely to be in the newest code added. That means that there are fewer places for bugs to hide. Once we verify a logical group of statements, we can rely on the following code more confidently.
The first step is opening the file and detecting when an error occurs. We write just enough code to complete these two tasks.
#include <iostream> #include <fstream> #include <iomanip> #include <string> using namespace std; int main() { ifstream in("rolodex.txt"); if (!in.good()) { cerr << "Unable to open \"rolodex.txt\"\n"; exit(1); } return 0; }
Parsing input is a rather complex and error-prone operation. If there is a problem with the program, it would be a shame to focus our attention on the parsing operation only to discover the problem was in the code reading the file. So, we write code that demonstrates that the program can read the file. However, this code is NOT part of the final program and must be removed or commented out of the final program.
#include <iostream> #include <fstream> #include <iomanip> #include <string> using namespace std; int main() { ifstream in("rolodex.txt"); if (!in.good()) { cerr << "Unable to open \"rolodex.txt\"\n"; exit(1); } string line; while (getline(in, line)) cout << line << endl; return 0; }
#include <iostream> #include <fstream> #include <iomanip> #include <string> using namespace std; int main() { ifstream in("rolodex.txt"); if (!in.good()) { cerr << "Unable to open \"rolodex.txt\"\n"; exit(1); } /*string line; while (getline(in, line)) cout << line << endl;*/ while (!in.eof()) // (a) { string name; // (b) getline(in, name, ':'); // (c) - 3-arguments cout << left << setw(20) << name; // (d) & (f) string address; // (b) getline(in, address, ':'); // (c) - 3-arguments cout << setw(35) << address; // (d) string phone; // (b) getline(in, phone); // (e) - 2-arguments cout << setw(20) << phone << endl; // (d) } return 0; }
getline
to read the last field. Reads text from the input stream in, stores the text in the string variable, and stops reading when the new line is encountered. Discards the new line.left
manipulator causes the output be be left justified in the space allocated by the setw
manipulator; notice the order of the two manipulators - it is important