May, 2005
The Format class is distributed as part of the string library. See the string library documentation on how to customise the include.h file for your compiler and for the file list.
This class is intended to provide a more convenient facility for formatting numerical data than is provided by the standard IO classes.
A typical application would look like this
Format F1, F2; ... load attributes into F1, F2; cout << F1 << x << y << F2 << z << endl;
Format F1 would be applied to x and y and F2 to z.
The variables x, y and z can be any of the following types: char, char*, String, int, unsigned int, long, unsigned long, double, float.
The manipulators endl, ends and flush are passed directly through to the ostream (such as cout).
One can also use the code
OstreamWithFormat f1(cout, F1); OstreamWithFormat f2(cout, F2); f1 << x << y; f2 << z << endl;
The attributes are loaded with statements like
F1.precision(2);You can recover their values with statements like
int p = F1.precision();
You can recover a pointer to the Format object from an OstreamWithFormat object , f1, with a statement like
Format& F1 = f1.format();
The following table shows the functions for accessing the attributes (preferred version in bold):
min_width sets the minimum field width and max_width the maximum field width. The program uses the smallest width required to present the number to the required precision and format type. If this is less than the minimum field width spaces are inserted to reach the desired field width. If the number won't fit within the maximum field width the action taken depends on the overflow or underflow policy.
The prefix and suffix strings are printed before and after the field. Their space is in addition to the space set by min_width and max_width.
The separator string is for use by other libraries when outputting data structures.
Variant = Format::VAR1 can give a better layout in columns of numbers using the SIG_FIGS format. Use a width value 2 more than the precision.
Integer objects use only the width, alignment, over flow policy, prefix and suffix properties. Convert an integer to double if you really want a decimal or scientific format type.
char* and String objects use only the width, alignment, prefix and suffix properties. Special characters such as \n are unlikely to be handled correctly.
char objects always use a field width of 1 and ignore the format properties.
To use the format library you need #include "format.h" in your .cpp files.
// Scientific format
Format SCI;
SCI.FormatType(Format::SCIENTIFIC);
SCI.Precision(8);
SCI.Width(14);
SCI.Suffix("|");
// Decimal format - switch to scientific on under-flow or over-flow
Format DEC1;
DEC1.UnderFlowPolicy(Format::E);
DEC1.FormatType(Format::DEC_FIGS);
DEC1.Precision(4);
DEC1.Width(12);
DEC1.Suffix("|");
// Decimal format - no action on under-flow; hashes on over-flow
Format DEC2;
DEC2.OverFlowPolicy(Format::HASH);
DEC2.FormatType(Format::DEC_FIGS);
DEC2.Precision(4);
DEC2.Width(12);
DEC2.Suffix("|");
// Significant figures - switch to scientific on under-flow or over-flow
Format SIG1;
SIG1.UnderFlowPolicy(Format::E);
SIG1.FormatType(Format::SIG_FIGS);
SIG1.Precision(8);
SIG1.Width(11);
SIG1.Positive(Format::SPACE);
SIG1.Prefix(" ");
SIG1.Suffix("|");
// Significant figures - reduce precision on under-flow; hashes on over-flow
Format SIG2;
SIG2.OverFlowPolicy(Format::HASH);
SIG2.FormatType(Format::SIG_FIGS);
SIG2.Precision(8);
SIG2.Width(11);
SIG2.Positive(Format::SPACE);
SIG2.Prefix(" ");
SIG2.Suffix("|");
// Significant figures - reduce precision on under-flow;
// scientific on over-flow; VAR1 variant
Format SIG3;
SIG3.UnderFlowPolicy(Format::ZERO);
SIG3.OverFlowPolicy(Format::E);
SIG3.FormatType(Format::SIG_FIGS);
SIG3.Precision(8);
SIG3.Width(10);
SIG3.Positive(Format::SPACE);
SIG3.Prefix(" ");
SIG3.Suffix("|");
SIG3.Variant(Format::VAR1);
// Integer format - switch to scientific on over-flow
Format INT;
INT.FormatType(Format::INTEGER);
INT.Width(12);
double x = 1.23456789;
double mult[] = {0, 1E-100, 1E-20, 0.0001, 0.1, 1, 10, 1000, 1E7, 1E8, 1E9,
1E10, 1E20, 1E100};
cout << SCI << "SCIENTFIC" << DEC1 << "DEC 1" << DEC2 << "DEC 2"
<< SIG1 << "SIG 1" << SIG2 << "SIG 2" << SIG3 << "SIG 3"
<< INT << "INTEGER" << endl;
for (i = 0; i < 14; ++i)
{
double y = x * mult[i];
cout << SCI << y << DEC1 << y << DEC2 << y << SIG1 << y
<< SIG2 << y << SIG3 << y << INT << y << endl;
}
cout << endl;
produces this output
SCIENTFIC| DEC 1| DEC 2| SIG 1| SIG 2| SIG 3| INTEGER 0.0000000e+00| 0.0000| 0.0000| 0.0000000| 0.0000000| .00000000| 0 1.2345679e-100| 1.2346e-100| 0.0000| 1.235e-100| 0.00000000| .00000000| 0 1.2345679e-20| 1.2346e-20| 0.0000| 1.2346e-20| 0.00000000| .00000000| 0 1.2345679e-04| 1.2346e-04| 0.0001| 1.2346e-04| 0.00012346| .00012346| 0 1.2345679e-01| 1.2346e-01| 0.1235| 0.12345679| 0.12345679| .12345679| 0 1.2345679e+00| 1.2346| 1.2346| 1.2345679| 1.2345679| 1.2345679| 1 1.2345679e+01| 12.3457| 12.3457| 12.345679| 12.345679| 12.345679| 12 1.2345679e+03| 1234.5679| 1234.5679| 1234.5679| 1234.5679| 1234.5679| 1235 1.2345679e+07|1.234568e+07|############| 12345679| 12345679| 12345679.| 12345679 1.2345679e+08|1.234568e+08|############| 123456790| 123456790| 123456790| 123456789 1.2345679e+09|1.234568e+09|############| 1234567900| 1234567900| 1.235e+09| 1234567890 1.2345679e+10|1.234568e+10|############| 1.2346e+10| ###########| 1.235e+10| 12345678900 1.2345679e+20|1.234568e+20|############| 1.2346e+20| ###########| 1.235e+20|1.234568e+20 1.2345679e+100|1.23457e+100|############| 1.235e+100| ###########| 1.23e+100|1.23457e+100