Exercise 7-7
Change the driver for the cross-reference program so that it writes line if there is only one line and lines otherwise.
Solution
The solution to this exercise is surprisingly simple. To clarify the question a bit – it essentially asks us to have some sort of if-else condition in place.
For instance…
- If the word “apple” occurs only on one line, we print “apple occurs on line: ” (followed by the line number).
- Otherwise, if the word “apple” occurs on multiple lines, we print “apple occurs on lines: ” (followed by the line numbers).
Recall that the Solution to Exercise 7-3 already provides the skeleton project that reports non-duplicated word occurrence line numbers. It therefore makes sense to use that project as the baseline project, and do the adjustment on top of it.
It turns out that there is only one small bit of code that needs changing, and it resides at the main.cpp file (the main function).
This is the original snippet within the main function:
// Write the word cout << it->first << " occurs on line(s): ";
We can change it easily to the following to achieve that if-else conditioning. We essentially resolves the number of non-duplicate line occurences for the word beforehand. We can then use it to construct the if-else logic and display either “line” or “lines” accordingly.
// Find number of lines the word has appeared vector<int>::size_type numLines = (it->second).size(); // Write the word cout << it->first << " occurs on "; if (numLines == 1) cout << "line: "; else cout << "lines: ";
Surprisingly simple.
The Project
Simply…
- Re-use that Project as per Solution to Exercise 7-3.
- Replace the main.cpp file as per followings.
#include <iostream> // std::cin, std::cout, std::endl #include <map> // std::map #include <string> // std::string #include <vector> // std::vector #include "xref.h" // xref using std::cin; using std::cout; using std::endl; using std::map; using std::string; using std::vector; // Find all the lines that refer to each word in the input // (S7.3/128) int main() { // Call xref using split by default. map<string, vector<int> > ret = xref(cin); // Write the results. for (map<string, vector<int> >::const_iterator it = ret.begin(); it != ret.end(); ++it) { // Find number of lines the word has appeared vector<int>::size_type numLines = (it->second).size(); // Write the word cout << it->first << " occurs on "; if (numLines == 1) cout << "line: "; else cout << "lines: "; // Followed by one or more line numbers. vector<int>::const_iterator line_it = it->second.begin(); cout << *line_it; // write the first line number ++line_it; // Write the rest of the line numbers, if any. while (line_it != it->second.end()) { cout << ", " << *line_it; ++line_it; } // Write a new line to separate each word from the next. cout << endl; } return 0; }
Test Result
Running this new version main code gives us the result as expected.
apple orange banana orange orange apple banana mango ^Z apple occurs on lines: 1, 3 banana occurs on lines: 1, 3 mango occurs on line: 4 orange occurs on lines: 1, 2