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