Justify a Text File

Problem

You want to right- or left-justify text.

Solution

Use streams and the standard stream formatting flags right and left that are part of ios_base, defined in . Example 4-29 shows how they work.

Example 4-29. Justify text

#include 
#include 
#include 
#include 

using namespace std;

int main(int argc, char** argv) {

 if (argc < 3)
 return(EXIT_FAILURE);

 ifstream in(argv[1]);
 ofstream out(argv[2]);

 int w = 72;
 if (argc == 4)
 w = atoi(argv[3]);

 string tmp;
 out.setf(ios_base::right); // Tell the stream to
 // right-justify
 while (!in.eof( )) {
 out.width(w); // Reset width after
 getline(in, tmp, '
'); // each write
 out << tmp << '
';
 }
 out.close( );
}

This example takes three arguments: an input file, an output file, and the width to right-justify to. You can use an input file like this:

With automatic download of Microsoft's (Nasdaq:
MSFT) enormous SP2 security patch to the Windows
XP operating system set to begin, the industry
still waits to understand its ramifications. Home
users that have their preferences set to receive
operating-system updates as they are made
available by Microsoft may be surprised to learn
that some of the software they already run on
their systems could be disabled by SP2 or may run
very differently.

and make it look like this:

 With automatic download of Microsoft's (Nasdaq:
 MSFT) enormous SP2 security patch to the Windows
 XP operating system set to begin, the industry
 still waits to understand its ramifications. Home
 users that have their preferences set to receive
 operating-system updates as they are made
 available by Microsoft may be surprised to learn
 that some of the software they already run on
 their systems could be disabled by SP2 or may run
 very differently.

The second text sample is right-justified to 50 characters.

Discussion

The ios_base class template has lots of flags for formatting numeric and text data that is read from or written to streams. The two that control how text is justified are right and left. They are static const members of ios_base, and are of type fmtflags (which is implementation defined); all of this stuff is defined in .

To set formatting flags, use ios_base::setf. This ORs the flags you pass in with the existing flags on the stream. For example, this line turns on right-justification:

out.setf(std::ios_base::right);

But right-justification doesn't make much sense without a righthand margin to butt up against. To set that margin, use ios_base::width, like this:

out.width(w);

This sets the width of the output field to the value passed in, meaning that when you right-justify text, the beginning of the string will be padded with spaces as much as is necessary to align the right end to the margin. Note that I set the width inside the loop while I set the right flag prior to the loop. I had to do this because the width resets to zero after each write to the stream. Format flags are not reset after writes, so I only had to initialize them once and be done with it.

It's always good to be tidy and responsible, though, so there is one more thing you should do when using format flags: clean up after yourself.

Often, the stream you are writing to does not belong to you, especially if you are writing a general-purpose library or API. For example, if you write a fancy logging function that takes an output stream and a string, modifies the string, sets the format flags, and writes it to the stream, you have potentially unwanted side-effects. After client code calls your logging function, its stream has potentially had its format flags rearranged. The solution is to copy the old ones and restore them when you're done.

For example, a responsible error logging function might look like this:

using namespace std;

void logError(ostream& out, const string& s) {

 string tmp(s);
 tmp.insert(0, "ERROR: ");

 ios_base::fmtflags flgs = // setf returns the
 out.setf(ios_base::left); // flags that were
 // already there
 out.width(72);
 out << tmp << '
';

 out.flags(flgs); // reset to original
}

The flags member function works similarly to setf, but it doesn't OR the flags you give it with the stream's current flags, it replaces them. Thus, when you call flags and pass in the original formatting flags, you can feel good that you cleaned up after yourself.

Building C++ Applications

Code Organization

Numbers

Strings and Text

Dates and Times

Managing Data with Containers

Algorithms

Classes

Exceptions and Safety

Streams and Files

Science and Mathematics

Multithreading

Internationalization

XML

Miscellaneous

Index



C++ Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2006
Pages: 241

Similar book on Amazon

Flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net