# Exercise 5-5

Write a function named center(const vector<string>&) that returns a picture in which all the lines of the original picture are padded out to their full width, and the padding is as evenly divided as possible between the left and right sides of the picture. What are the properties of pictures for which such a function is useful? How can you tell whether a given picture has these properties?

# Solution

When I first saw this question, straight away it reminded me of the frame function that the author built in Chapter 5 / my Solution to Exercise 5-0 (Part 3/3). The original frame function effectively pad all the strings with empty spaces, making all strings equal width and left aligned, and put a frame around it to make it “box-like” when we display the vector<string> line by line vertically – like a formatted article.

Also recall that in my Solution to Exercise 5-1 (about building a permuted index page), I modified the frame function so that it takes on additional parameters regarding whether the padding should be left-aligned or right-aligned. So instead of creating a brand new function center(const vector<string>&), I may as well reuse the frame function and enhance it so that we have an extra option to center-aligned.

In this post I shall describe how I modify the frame function to allow user to center-align the vector<string> “picture text”.

## Algorithm

We know what the algorithm looks like for left-align and right-align for the frame function from Solution to Exercise 5-1. The algorithm for center-aligned is very similar. i.e. we use the width function to identify the max length of the string (within the vector<string>). We then compute how many padding spaces are required on both (left and right) sides of each individual text string – the padding on the left should be more or less the same as the right. The diagram below essentially summarises the equations in computing the various lengths required.

These equations are reflected in the enhanced frame.cpp code below.

## The Project

Let me wrap up the whole project here – we should be able to figure out how the enhanced frame function works, and how we can easily use it. (Note that I have reused the knowledge / experience gained from the previous exercises in Chapter 5).

(The enhanced frame function is the answer to the exercise – the other codes are wrapped together for demonstration purposes.)

• main.cpp
• frame.h
• frame.cpp
• vout.h
• vout.cpp

#### main.cpp

#include <iostream>
#include <string>
#include <vector>
#include "frame.h"
#include "vcout.h"

using std::string;
using std::vector;

int main()
{

// read lines via standard console input and append to article

// padded each line of the article

// display the now padded article

return 0;
}


#### 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>&, const std::string&, const char);

#endif // GUARD_FRAME_H


#### 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, const string& align, char c)
{
vector<string> ret;

typedef string::size_type stringSize;
stringSize  maxlen = width(v);
string symbol(1, c);
string border(maxlen + 4, c);

// 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)
if (align == "left")
ret.push_back(symbol + " " + v[i] + string(maxlen - v[i].size(), ' ') + " " + symbol);
else if (align == "right")
ret.push_back(symbol + " " + string(maxlen - v[i].size(), ' ') + v[i]  + " " + symbol);
else if (align == "center")
{
stringSize leftPadSize = (maxlen - v[i].size() ) / 2 ;
stringSize midLineSize = v[i].size();
+ v[i] + string(rightPadSize, ' ') + " " + symbol;
}

// write the bottom border
ret.push_back(border);

return ret;
}


#ifndef GUARD_READ_LINES_H

#include <string>
#include <vector>



#include <string>    // string
#include <vector>    // vector
#include <iostream>   // cin, getline

using std::string;
using std::vector;
using std::cin;
using std::getline;

// Read lines and return the line collection
{
string line;
vector<string> ret;
while (getline(cin, line))
ret.push_back(line);

return ret;
}


#### vout.h

#ifndef GUARD_VCOUT_H
#define GUARD_VCOUT_H

#include <string>
#include <vector>

int vcout(const std::vector<std::string>&);

#endif // GUARD_VCOUT_H


#### vout.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;
}


# Test Program

## Test 1 – Center Align

Update this line in main program:

vector<string> paddedArticle = frame(article,"center",'*');


Test Result:

this is an
example
to
illustrate
framing
^Z
**************
* this is an *
*  example   *
*     to     *
* illustrate *
*  framing   *
**************


## Test 2 – Left Align

Update this line in main program:

vector<string> paddedArticle = frame(article,"left",'*');


Test Result:

this is an
example
to
illustrate
framing
^Z
**************
* this is an *
* example    *
* to         *
* illustrate *
* framing    *
**************


## Test 3 – Right Align

Update this line in main program:

vector<string> paddedArticle = frame(article,"right",'*');


Test Result:

this is an
example
to
illustrate
framing
^Z
**************
* this is an *
*    example *
*         to *
* illustrate *
*    framing *
**************


# Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

## One thought on “Accelerated C++ Solution to Exercise 5-5”

1. Martin says:

You have centred a picture within a frame. My solution centres a picture not a frame, which is what the question asks. Of course, my output then could be passed into another function to add a frame! This splits to two processes.