This is Part 3 of the 3-part Solution to Exercise 5-0.
Exercise 5-0 (Part 3 / 3)
This is a fairly clever yet simple-to-understand program. This exercise demonstrates 4 things: (1) how to create a paragraph and store in the form of a vector<string> container, (2) how to display the paragraph with and without a frame, (3) how to concatenate two paragraph “pictures” vertically, (4) how to concatenate two paragraph “pictures” horizontally.
The Program Logic
- User to create a paragraph by providing multiple lines of input, via the console window.
- The program store the paragraph in the form of a vector<string> container called p – each string element corresponds the an input line. e.g. p[0] is the first line, p[1] is the second line, etc.
- A function called vcout may be used to display a vector<string> container in the form of a paragraph via the console window.
- A function called frame may be used to take in a vector<string> container and return a new vector<string> container representing a “framed” paragraph.
- A function called vcat may be used to concatenate multiple paragraph “box-like pictures” vertically. e.g. imagine two box-like paragraph pictures are stacked vertically.
- A function called hcat may be used to concatenate multiple paragraph “box-like pictures” horizontally. e.g. imagine two box-like paragraph pictures are aligned horizontally.
- An sub-function called width (used by the frame and hcat functions) is in place to ensure the paragraphs behave in a “box-like” shape when we add a frame around it, or concatenate horizontally.
- Within the main program, we apply the functions vcout, frame, vcat, and hcat in multiple combinations to demonstrate it is very easy to display the vector<string> p in the form of “box-like pictures” and in multiple ways. e.g. apply a frame around a paragraph, stack the two box-like picture paragraphs vertically / horizontally.
The Project
This is what the management tree looks like in Code::Block:
C++ Source Files
- main.cpp – this is the first program that is run during the implementation phase.
- frame.cpp – contains the frame and width functions.
- hcat.cpp – contains the hcat function.
- vcat.cpp – contains the vcat function.
- vcout.cpp – contains the vcout function.
C++ Header Files
- frame.h – declare the functions in frame.cpp.
- hcat.h – declare the functions in hcat.cpp.
- vcat.h – declare the functions in vcat.cpp.
- vcout.h – declare the functions in vcout.cpp.
Source Files
main.cpp
#include <iostream> // cin, cout, endl, getline #include <vector> // vector #include <string> // string #include "frame.h" // width, frame #include "vcat.h" // vcat #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: p \n" "----------------------------------------------------\n"; vcout(p); cout << "-----------------------------------------------------\n" "Display: frame(p) \n" "-----------------------------------------------------\n"; vcout(frame(p)); cout << "-----------------------------------------------------\n" "Display: vcat(p, frame(p)) \n" "-----------------------------------------------------\n"; vcout(vcat(p,frame(p))); cout << "-----------------------------------------------------\n" "Display: vcat(frame(p), p) \n" "-----------------------------------------------------\n"; vcout(vcat(frame(p),p)); 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)); cout << "-----------------------------------------------------\n" "Display: vcat(hcat(frame(p), p), hcat(p, frame(p))) \n" "-----------------------------------------------------\n"; vcout(vcat(hcat(frame(p), p), hcat(p, frame(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>::size_type i = 0; i != v.size(); ++i) maxlen = max(maxlen, v[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>::size_type i = 0; i != v.size(); ++i) ret.push_back("* " + v[i] + string(maxlen - v[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>::size_type i = 0, j = 0; // continue until we've seen all rows from both pictures while (i != left.size() || j != right.size()) { // 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.size()) s = left[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.size()) s += right[j++]; // add s to the picture we are creating ret.push_back(s); } return ret; }
vcat.cpp
#include <string> // string #include <vector> // vector using std::string; using std::vector; vector<string> vcat(const vector<string>& top, const vector<string>& bottom) { // copy the top picture vector<string> ret = top; // copy entire bottom picture (option 1 and option 2 have the same effect - pick whichever!) // option 1 for (vector<string>::const_iterator it = bottom.begin(); it != bottom.end(); ++it) ret.push_back(*it); // option 2 /* ret.insert(ret.end(), bottom.begin(), bottom.end()); */ return ret; }
vcout.cpp
#include <iostream> #include <string> // string #include <vector> // vector using std::cout; using std::endl; using std::string; using std::vector; int vcout(const vector<string>& v) { for (vector<string>::const_iterator iter = v.begin(); iter != v.end(); ++iter) { cout << (*iter) << endl; } return 0; }
Header Files
frame.h
#ifndef GUARD_FRAME_H #define GUARD_FRAME_H #include <string> #include <vector> std::string::size_type width(const std::vector<std::string>&); std::vector<std::string> frame(const std::vector<std::string>&); #endif // GUARD_FRAME_H
hcat.h
#ifndef GUARD_HCAT_H #define GUARD_HCAT_H #include <string> #include <vector> std::vector<std::string> hcat(const std::vector<std::string>&, const std::vector<std::string>&); #endif // GUARD_HCAT_H
vcat.h
#ifndef GUARD_VCAT_H #define GUARD_VCAT_H #include <string> #include <vector> std::vector<std::string> vcat(const std::vector<std::string>&, const std::vector<std::string>&); #endif // GUARD_VCAT_H
vcout.h
#ifndef GUARD_VCOUT_H #define GUARD_VCOUT_H #include <string> #include <vector> int vcout(const std::vector<std::string>&); #endif // GUARD_VCOUT_H
Test Program
I have written the main program in a way that is easy enough to test out multiple combination of function usage (i.e. frame, vcat, and hcat) against the vector<string> p (the paragraph).
In this test, as soon as the program starts up, I provide the following 5 lines (followed by the end-of-file button. i.e. F6 for Windows).
- this is an
- example
- to
- illustrate
- framing
Test Result
this is an example to illustrate framing ^Z ---------------------------------------------------- Display: p ---------------------------------------------------- this is an example to illustrate framing ----------------------------------------------------- Display: frame(p) ----------------------------------------------------- ************** * this is an * * example * * to * * illustrate * * framing * ************** ----------------------------------------------------- Display: vcat(p, frame(p)) ----------------------------------------------------- this is an example to illustrate framing ************** * this is an * * example * * to * * illustrate * * framing * ************** ----------------------------------------------------- Display: vcat(frame(p), p) ----------------------------------------------------- ************** * this is an * * example * * to * * illustrate * * framing * ************** this is an example to illustrate framing ----------------------------------------------------- Display: hcat(p, frame(p)) ----------------------------------------------------- this is an ************** example * this is an * to * example * illustrate * to * framing * illustrate * * framing * ************** ----------------------------------------------------- Display: hcat(frame(p), p) ----------------------------------------------------- ************** this is an * this is an * example * example * to * to * illustrate * illustrate * framing * framing * ************** ----------------------------------------------------- Display: vcat(hcat(frame(p), p), hcat(p, frame(p))) ----------------------------------------------------- ************** this is an * this is an * example * example * to * to * illustrate * illustrate * framing * framing * ************** this is an ************** example * this is an * to * example * illustrate * to * framing * illustrate * * framing * **************
This is overall a very nice program that demonstrates the ease of manipulating a vector as long as the functions are well written and in place.