Format class

May, 2005

Introduction

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):

attribute default value possible values description
min_width
MinWidth
0 non-negative integer minimum field width
max_width
MaxWidth
12 positive integer maximum field width
width
Width
  positive integer sets both min_width and max_width
overflow_policy
OverFlowPolicy
Format::E Format::E on overflow use scientific format
Format::HASH on overflow replace field with # characters
underflow_policy
UnderFlowPolicy
Format::ZERO Format::E on underflow use scientific format
Format::HASH on underflow replace field with # characters
Format::ZERO reduce precision
alignment
Alignment
Format::RIGHT Format::LEFT left alignment
Format::RIGHT right alignment
Format::CENTRE
Format::CENTER
centre (center) alignment
format_type
FormatType
Format::SIG_FIGS Format::SIG_FIGS precision shows number of significant figures
Format::DEC_FIGS precision shows number of decimal figures
Format::SCIENTIFIC scientific (E) format
Format::INTEGER round to an integer
positive
Positive
Format::NX Format::PLUS non-negative numbers preceded by +
Format::SPACE non-negative numbers preceded by space
Format::NX no additional character preceding non-negative number
precision
Precision
2 non-negative integer number of decimal or significant figures
prefix
Prefix
"" String or char* prefix string
suffix
Suffix
"" String or char* suffix string
separator
Separator
"," String or char* separator string
variant
Variant
Format::VAR0 Format::VAR0 default setting
Format::VAR1 Affects SIG_FIGS and DEC_FIGS formats. For number less than 1 in absolute value, there is no 0 before the decimal point; number with no decimal places will have a decimal point if there is room.

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.

Example

// 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