Exercise 6-1
Reimplement the frame and hcat operations from S5.8.1/93 and $5.8.3/94 to use iterators.
Solution
The ask for this exercise is to reimplement the frame.cpp and hcat.cpp (as seen in Chapter 5 / my Solution to Exercise 5-0 (Part 3/3)), from index-base access iterator-base access.
I personally think this is a very good exercise to enable us to practice a bit on accessing vector elements by either index or iterator. This is summarised by the diagram below:
Bearing this in mind, it is in fact not that difficult, to convert frame and hcat operations from using index to iterators.
The Project
All the source and header files are essentially the same as my Solution to Exercise 5-0 (Part 3/3). In this exercise we, however, amend the frame.cpp and hcat.cpp to use iterator (instead of using index). I have also updated the main.cpp to enable us to test out the change easily. (i.e. use the Project structure as per Exercise 5-0 (Part 3/3) but use the new main.cpp, frame.cpp, and hcat.cpp. Then run the program to test.
Source File List (Newly re-written)
Source Files (Newly re-written)
main.cpp
#include <iostream> // cin, cout, endl, getline #include <vector> // vector #include <string> // string #include "frame.h" // frame #include "hcat.h" // hcat #include "vcout.h" // vcout using std::cin; using std::cout; using std::endl; using std::getline; using std::string; using std::vector; int main() { string s; // line vector<string> p; // paragraph // read multiple lines to make a paragraph while (getline(cin, s)) p.push_back(s); // have a play, manipulate and display paragraph (p) in multiple ways cout << "-----------------------------------------------------\n" "Display: hcat(p, frame(p)) \n" "-----------------------------------------------------\n"; vcout(hcat(p,frame(p))); cout << "-----------------------------------------------------\n" "Display: hcat(frame(p), p) \n" "-----------------------------------------------------\n"; vcout(hcat(frame(p),p)); return 0; }
frame.cpp
#include <string> // string #include <vector> // vector #include <algorithm> // max using std::string; using std::vector; using std::max; string::size_type width(const vector<string>& v) { string::size_type maxlen = 0; for(vector<string>::const_iterator i = v.begin(); i != v.end(); ++i) maxlen = max(maxlen, i->size()); return maxlen; } vector<string> frame(const vector<string>& v) { vector<string> ret; string::size_type maxlen = width(v); string border(maxlen + 4, '*'); // write the top border ret.push_back(border); // write each interior row, bordered by an asterisk and a space for (vector<string>::const_iterator i = v.begin(); i != v.end(); ++i) ret.push_back("* " + (*i) + string(maxlen - i->size(), ' ') + " *"); // write the bottom border ret.push_back(border); return ret; }
hcat.cpp
#include <string> // string #include <vector> // vector #include "frame.h" // width using std::string; using std::vector; vector<string> hcat(const vector<string>& left, const vector<string>& right) { vector<string> ret; // add 1 to leave a space between pictures string::size_type width1 = width(left) + 1; // indices to look at elements from left and right respectively vector<string>::const_iterator i = left.begin(); vector<string>::const_iterator j = right.begin(); // continue until we've seen all rows from both pictures while (i != left.end() || j != right.end()) { // construct new string to hold characters from both pictures string s; // copy a row from the left-hand side, if there is one if (i != left.end()) s = *(i++); // pad to full width s += string(width1 - s.size(), ' '); // copy a row from teh right-hand side, if there is one if (j != right.end()) s += *(j++); // add s to the picture we are creating ret.push_back(s); } return ret; }
Test Program
Running the program gives us the output as expected. This effectively demonstrates that, if the code is written correctly, there is virtually no difference between accessing vector elements by index or by iterators.
Hello world how are we today? ^Z ----------------------------------------------------- Display: hcat(p, frame(p)) ----------------------------------------------------- Hello world *************** how are * Hello world * we today? * how are * * we today? * *************** ----------------------------------------------------- Display: hcat(frame(p), p) ----------------------------------------------------- *************** Hello world * Hello world * how are * how are * we today? * we today? * ***************