Add Margins to a Text File

Problem

Given a text file, you want to add margins to it. In other words, you want to pad either side of each line with some character so that each line is the same width.

Solution

Example 4-28 shows how to add margins to a file using streams, strings, and the getline function template.

Example 4-28. Adding margins to a text file

#include #include #include #include using namespace std; const static char PAD_CHAR = '.'; // addMargins takes two streams and two numbers. The streams are for // input and output. The first of the two numbers represents the // left margin width (i.e., the number of spaces to insert at the // beginning of every line in the file). The second number represents // the total line width to pad to. void addMargins(istream& in, ostream& out, int left, int right) { string tmp; while (!in.eof( )) { getline(in, tmp, ' '); // getline is defined // in tmp.insert(tmp.begin( ), left, PAD_CHAR); rpad(tmp, right, PAD_CHAR); // rpad from Recipe // 4.2 out << tmp << ' '; } } int main(int argc, char** argv) { if (argc < 3) return(EXIT_FAILURE); ifstream in(argv[1]); ofstream out(argv[2]); if (!in || !out) return(EXIT_FAILURE); int left = 8; int right = 72; if (argc == 5) { left = atoi(argv[3]); right = atoi(argv[4]); } addMargins(in, out, left, right); out.close( ); if (out) return(EXIT_SUCCESS); else return(EXIT_FAILURE); }

This example makes a few assumptions about the format of the incoming text, so be sure to read the next section for details.

Discussion

addMargins assumes your input looks something like this:

The data is still inconclusive. But the weakness in job creation and the apparent weakness in high-paying jobs may be opposite sides of a coin. Companies still seem cautious, relying on temporary workers and anxious about rising health care costs associated with full-time workers.

This text is wrapped at 50 characters (see Recipe 4.16), and is left justified (see Recipe 4.20). addMargins also assumes you want your output to look something like the following, which uses periods instead of spaces to show where the padding has been done:

........The data is still inconclusive. But the weakness................ ........in job creation and the apparent weakness in.................... ........high-paying jobs may be opposite sides of a coin................ ........Companies still seem cautious, relying on....................... ........temporary workers and anxious about rising health............... ........care costs associated with full-time workers....................

By default, the left margin is eight characters and the total line length is 72. Of course, if you know your input text will always be left and right justified, you can simply pad each end of each line with as many characters as you see fit. Either way, the logic is straightforward. Many of the techniques used in this recipe have been covered already (streams, padding a string), so I won't discuss them here. The one function that has not yet appeared is getline.

If you want to read in text a line at a time, or to be more precise, you want to read in text up to a particular delimiter, use the getline function template defined in , as I did in Example 4-28:

getline(in, tmp, ' ');

getline reads characters from the input stream and appends them to tmp until the delimiter ' ' is reached, which is not appended to tmp. basic_istream has a member function by the same name, but it behaves differently. It stores its output in a character buffer, not a string. In this case, I want to take advantage of string member functions, and don't want to have to read a line into a character buffer redundantly and then copy that into a string, so I used the string version of getline.

See Also

Recipe 4.16 and Recipe 4.20

Категории