Jump to content

C++ Programming/Code/IO

From Wikibooks, open books for an open world

Also commonly referenced as the C++ I/O of the C++ Standard Library, since the library also includes the C Standard library and its I/O implementation, as seen before in the Standard C I/O Section.

Input and output are essential for any computer software, as these are the only means by which the program can communicate with the user. The simplest form of input/output is pure textual, i.e. the application displays in console form, using simple ASCII characters to prompt the user for inputs, which are supplied using the keyboard.

There are many ways for a program to gain input and output, including

  • File i/o, that is, reading and writing to files
  • Console i/o, reading and writing to a console window, such as a terminal in UNIX-based operating systems or a DOS prompt in Windows.
  • Network i/o, reading and writing from a network device
  • String i/o, reading and writing treating a string as if it were the input or output device

While these may seem unrelated, they work very similarly. In fact, operating systems that follow the POSIX specification deal with files, devices, network sockets, consoles, and many other things all with one type of handle, a file descriptor. However, low-level interfaces provided by the operating system tend to be difficult to use, so C++, like other languages, provide an abstraction to make programming easier. This abstraction is the stream.

Character encoding

[edit | edit source]
Clipboard

To do:
Complete character encoding info


American Standard Code for Information Interchange (ASCII) 95 chart

[edit | edit source]

ASCII is a character-encoding scheme based on the ordering of the English alphabet. The 95 ASCII graphic characters numbered from 0x20 to 0x7E (32 to 126 decimal), also known as the printable characters, represent letters, digits, punctuation marks, and a few miscellaneous symbols. The first 32 ASCII characters, from 0x00 to 0x20, are known as control characters. The space character, that denotes the space between words, as produced by the space-bar of a keyboard, represented by code 0x20 (hexadecimal), is considered a non-printing graphic (or an invisible graphic) rather than a control character.

Binary Oct Dec Hex Glyph
010 0000 040 32 20 space
010 0001 041 33 21 !
010 0010 042 34 22 "
010 0011 043 35 23 #
010 0100 044 36 24 $
010 0101 045 37 25 %
010 0110 046 38 26 &
010 0111 047 39 27 '
010 1000 050 40 28 (
010 1001 051 41 29 )
010 1010 052 42 2A *
010 1011 053 43 2B +
010 1100 054 44 2C ,
010 1101 055 45 2D -
010 1110 056 46 2E .
010 1111 057 47 2F /
011 0000 060 48 30 0
011 0001 061 49 31 1
011 0010 062 50 32 2
011 0011 063 51 33 3
011 0100 064 52 34 4
011 0101 065 53 35 5
011 0110 066 54 36 6
011 0111 067 55 37 7
011 1000 070 56 38 8
011 1001 071 57 39 9
011 1010 072 58 3A :
011 1011 073 59 3B ;
011 1100 074 60 3C <
011 1101 075 61 3D =
011 1110 076 62 3E >
011 1111 077 63 3F ?
Binary Oct Dec Hex Glyph
100 0000 100 64 40 @
100 0001 101 65 41 A
100 0010 102 66 42 B
100 0011 103 67 43 C
100 0100 104 68 44 D
100 0101 105 69 45 E
100 0110 106 70 46 F
100 0111 107 71 47 G
100 1000 110 72 48 H
100 1001 111 73 49 I
100 1010 112 74 4A J
100 1011 113 75 4B K
100 1100 114 76 4C L
100 1101 115 77 4D M
100 1110 116 78 4E N
100 1111 117 79 4F O
101 0000 120 80 50 P
101 0001 121 81 51 Q
101 0010 122 82 52 R
101 0011 123 83 53 S
101 0100 124 84 54 T
101 0101 125 85 55 U
101 0110 126 86 56 V
101 0111 127 87 57 W
101 1000 130 88 58 X
101 1001 131 89 59 Y
101 1010 132 90 5A Z
101 1011 133 91 5B [
101 1100 134 92 5C \
101 1101 135 93 5D ]
101 1110 136 94 5E ^
101 1111 137 95 5F _
Binary Oct Dec Hex Glyph
110 0000 140 96 60 `
110 0001 141 97 61 a
110 0010 142 98 62 b
110 0011 143 99 63 c
110 0100 144 100 64 d
110 0101 145 101 65 e
110 0110 146 102 66 f
110 0111 147 103 67 g
110 1000 150 104 68 h
110 1001 151 105 69 i
110 1010 152 106 6A j
110 1011 153 107 6B k
110 1100 154 108 6C l
110 1101 155 109 6D m
110 1110 156 110 6E n
110 1111 157 111 6F o
111 0000 160 112 70 p
111 0001 161 113 71 q
111 0010 162 114 72 r
111 0011 163 115 73 s
111 0100 164 116 74 t
111 0101 165 117 75 u
111 0110 166 118 76 v
111 0111 167 119 77 w
111 1000 170 120 78 x
111 1001 171 121 79 y
111 1010 172 122 7A z
111 1011 173 123 7B {
111 1100 174 124 7C |
111 1101 175 125 7D }
111 1110 176 126 7E ~


Streams

[edit | edit source]

A stream is a type of object from which we can take values, or to which we can pass values. This is done transparently in terms of the underlying code that demonstrates the use of the std::cout stream, known as the standard output stream.

// 'Hello World!' program 
 
#include <iostream>
 
int main()
{
  std::cout << "Hello World!" << std::endl;
  return 0;
}


Almost all input and output one ever does can be modeled very effectively as a stream. Having one common model means that one only has to learn it once. If you understand streams, you know the basics of how to output to files, the screen, sockets, pipes, and anything else that may come up.

A stream is an object that allows one to push data in or out of a medium, in order. Usually a stream can only output or can only input. It is possible to have a stream that does both, but this is rare. One can think of a stream as a car driving along a one-way street of information. An output stream can insert data and move on. It (usually) cannot go back and adjust something it has already written. Similarly, an input stream can read the next bit of data and then wait for the one that comes after it. It does not skip data or rewind and see what it had read five minutes ago.

The semantics of what a stream's read and write operations do depend on the type of stream. In the case of a file, an input file stream reads the file's contents in order without rewinding, and an output file stream writes to the file in order. For a console stream, output means displaying text, and input means getting input from the user via the console. If the user has not inputted anything, then the program blocks, or waits, for the user to enter in something.


Clipboard

To do:
Remember to complete with the String Stream class and include the various io stream format flags.


iostream

[edit | edit source]
c++ program that uses iostream to save output to the file

iostream is a header file used for input/output. It is part of the C++ standard library. The name stands for Input/Output Stream. In C++ there is no special syntax for streaming data input or output. Instead, these are combined as a library of functions. Like we have seen with the C Standard Library use of <cstdio> header, iostream provides basic OOP services for I/O.

The iostream automatically defines and uses a few standard objects:

  • cin, an object of the istream class that reads data from the standard input device.
  • cout, an object of the ostream class, which displays data to the standard output device.
  • cerr, another object of the ostream class that writes unbuffered output to the standard error device.
  • clog, like cerr, but uses buffered output.

for sending data to and from the standard streams input, output, error (unbuffered), and error (buffered) respectively. As part of the C++ standard library, these objects are a part of the std namespace.

Standard input, output, and error

The most common streams one uses are cout, cin, and cerr (pronounced "c out", "c in", and "c err(or)", respectively). They are defined in the header <iostream>. Usually, these streams read and write from a console or terminal. In UNIX-based operating systems, such as Linux and Mac OS X, the user can redirect them to other files, or even other programs, for logging or other purposes. They are analogous to stdout, stdin, and stderr found in C. cout is used for generic output, cin is used for input, and cerr is used for printing errors. (cerr typically goes to the same place as cout, unless one or both is redirected, but it is not buffered and allows the user to fine-tune which parts of the program's output is redirected where.)

Output
[edit | edit source]

The standard syntax for outputting to a stream, in this case, cout, is

cout << some_data << some_more_data;

Example

#include <iostream>

using namespace std;

int main()
{
  int iA = 1;
  cout << "Hello, World! " << iA << '\n';

  return 0;
}

Result of Execution

Hello, World! 1

To add a line break, send a newline character, \n. Using std::endl also outputs a newline character, but it also calls os.flush().

Example

#include <iostream>
#include <ostream>

using namespace std;

int main()
{
  int iA = 1;
  char ch = 13;
  cout << "Hello, World!" << "\n" << iA << "\n" << ch << endl;

  return 0;
}

Execution

Hello, World!
1

It is always a good idea to end your output with a blank line, so as to not mess up with user's terminals.

As seen in the "Hello, World!" program, we direct the output to std::cout. This means that it is a member of the standard library. For now, don't worry about what this means; we will cover the library and namespaces in later chapters.

What you do need to remember is that, in order to use the output stream, you must include a reference to the standard IO library, as shown here:

#include <iostream>

This opens up a number of streams, functions and other programming devices that we can now use. For this section, we are interested in two of these; std::cout and std::endl.

Once we have referenced the standard IO library, we can use the output stream very simply. To use a stream, give its name, then pipe something in or out of it, as shown:

std::cout << "Hello, World!";

The << operator feeds everything to the right of it into the stream. We have essentially fed a text object into the stream. That's as far as our work goes; the stream now decides what to do with that object. In the case of the output stream, it's printed on-screen.

We're not limited to only sending a single object type to the stream, nor indeed are we limited to one object a time. Consider the examples below:

 std::cout << "Hello, " << "Joe"<< std::endl;
 std::cout << "The answer to life, the universe and everything is " << 42 << std::endl;

As can be seen, we feed in various values, separated by a pipe character. The result comes out something like:

Hello, Joe
The answer to life, the universe and everything is 42

You will have noticed the use of std::endl throughout some of the examples so far. This is a special manipulator, which not only outputs a newline character but also calls os.flush().

Input
[edit | edit source]

What would be the use of an application that only ever outputted information, but didn't care about what its users wanted? Minimal to none. Fortunately, inputting is as easy as outputting when you're using the stream.

The standard input stream is called std::cin and is used very similarly to the output stream. Once again, we instantiate the standard IO library:

#include <iostream>

This gives us access to std::cin (and the rest of that class). Now, we give the name of the stream as usual, and pipe output from it into a variable. A number of things have to happen here, demonstrated in the example below:

#include <iostream>
int main(int iArgc, char a_chArgv[]) {
  int iA;
  std::cout << "Hello! How old are you? ";
  std::cin >> iA;
  std::cout << "You're really " << iA << " years old?" << std::endl;
 
  return 0;
}

We instantiate the standard IO library as usual, and call our main function in the normal way. Now we need to consider where the user's input goes. This calls for a variable (discussed in a later chapter) that we declare as being called a.

Next, we send some output, asking the user for their age. The real input happens now; everything the user types until they hit Enter is going to be stored in the input stream. We pull this out of the input stream and save it in our variable.

Finally, we output the user's age, piping the contents of our variable into the output stream.

Note: You will notice that, if anything other than a whole number is entered, the program will crash. This is due to the way in which we set up our variable. Don't worry about this for now; we will cover variables later on.

A Program Using User Input
[edit | edit source]

The following program inputs two numbers from the user and prints their sum:

 #include <iostream>
 
 int main()
 {
    int iNumber1, iNumber2;
    std::cout << "Enter number 1: ";
    std::cin >> iNumber1;
    std::cout << "Enter number 2: ";
    std::cin >> iNumber2;
    std::cout << "The sum of " << iNumber1 << " and " << iNumber2 << " is "
               << iNumber1 + iNumber2 << ".\n";
    return 0;
 }

Just like std::cout that represents the standard output stream, the C++ library provides (and the iostream header declares) the object std::cin representing standard input, which usually gets input from the keyboard. The statement:

 std::cin >> iNumber1;

uses the extraction operator (>>) to get an integer input from the user. When used to input integers, any leading whitespace is skipped, a sequence of valid digits optionally preceded by a + or - sign is read and the value stored in the variable. Any remaining characters in the user input are not consumed. These would be considered next time some input operation is performed.

If you want the program to use a function from a specific namespace, normally you must specify which namespace the function is in. The above example calls to cout, which is a member of the std namespace (hence std::cout). If you want a program to specifically use the std namespace for an identifier, which essentially removes the need for all future scope resolution (e.g. std::), you could write the above program like this:

#include <iostream>
 
using namespace std;

int main()
{
    int iNumber1, iNumber2;
    cout << "Enter number 1: ";
    cin >> iNumber1;
    cout << "Enter number 2: ";
    cin >> iNumber2;
    cout << "The sum of " << iNumber1 << " and " << iNumber2 << " is "
               << iNumber1 + iNumber2 << ".\n";
    return 0;
}

Please note that 'std' namespace is the namespace defined by standard C++ library.

Manipulators
[edit | edit source]

A manipulator is a function that can be passed as an argument to a stream in different circumstances. For example, the manipulator 'hex' will cause the stream object to format subsequent integer input to the stream in hexadecimal instead of decimal. Likewise, 'oct' results in integers displaying in octal, and 'dec' reverts back to decimal.

Example

#include <iostream>
using namespace std;

int main()
{
  cout << dec << 16 << ' ' << 10 << "\n";
  cout << oct << 16 << ' ' << 10 << "\n";
  cout << hex << 16 << ' ' << 10 << endl;

  return 0;
}

Execution

16 10
20 12
10 a

There are many manipulators that can be used in conjunction with streams to simplify the formatting of input. For example, 'setw()' sets the field width of the data item next displayed. Used in conjunction with 'left' and 'right'(that set the justification of the data), 'setw' can easily be used to create columns of data.

Example

#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
	cout << setw(10) << right << 90 << setw(8) << "Help!\n";
	cout << setw(10) << left << 45 << setw(8) << "Hi!" << endl;

	return 0;
}

Execution

        90   Help!
45        Hi!

The data in the top row display at the right of the columns created by 'setw', while in the next row, the data is left justified in the column. Please note the inclusion of a new library 'iomanip'. Most formatting manipulators require this library.

Here are some other manipulators and their uses:

Manipulator Function
boolalpha displays boolean values as 'true' and 'false' instead of as integers.
noboolalpha forces bools to display as integer values
showuppercase converts strings to uppercase before displaying them
noshowuppercase displays strings as they are received, instead of in uppercase
fixed forces floating point numbers to display with a fixed number of decimal places
scientific displays floating point numbers in scientific notation
Buffers
[edit | edit source]

Most stream objects, including 'cout' and 'cin', have an area in memory where the information they are transferring sits until it is asked for. This is called a 'buffer'. Understanding the function of buffers is essential to mastering streams and their use.

Example

#include <iostream>
using namespace std;

int main()
{
  int iNumber1, iNumber2;
  cin >> iNumber1;
  cin >> iNumber2;

  cout << "Number1: " << iNumber1 << "\n"
       << "Number2: " << iNumber2 << endl;

  return 0;
}

Execution 1

>74
>27
Number1: 74
Number2: 27

The inputs are given separately, with a hard return between them. '>' denotes user input.

Execution 2

>74 27
Number1: 74
Number2: 27

The inputs are entered on the same line. They both go into the 'cin' stream buffer, where they are stored until needed. As 'cin' statements are executed, the contents of the buffer are read into the appropriate variables.

Execution 3

>74 27 56
Number1: 74
Number2: 27

In this example, 'cin' received more input than it asked for. The third number it read in, 56, was never inserted into a variable. It would have stayed in the buffer until 'cin' was called again. The use of buffers can explain many strange behaviors that streams can exhibit.

Example

#include <iostream>
using namespace std;

int main()
{
  int iNumber1, iNumber2, iNumber3;
  cin >> iNumber1 >> iNumber2;

  cout << "Number1: " << iNumber1 << "\n"
    << "Number2: " << iNumber2 << endl;

  cin >> iNumber3;

  cout << "Number3: " << iNumber3 << endl;

  return 0;
}

Execution

>45 89 37
Number1: 45
Number2: 89
Number3: 37

Notice how all three numbers were entered at the same time in one line, but the stream only pulled them out of the buffer when they were asked for. This can cause unexpected output, since the user might accidentally put an extra space into his input. A well written program will test for this type of unexpected input and handle it gracefully.

ios is a header file in the C++ standard library that defines several types and functions basic to the operation of iostreams. This header is typically included automatically by other iostream headers. Programmers rarely include it directly.

Typedefs
[edit | edit source]
Name description
ios Supports the ios class from the old iostream library.
streamoff Supports internal operations.
streampos Holds the current position of the buffer pointer or file pointer.
streamsize Specifies the size of the stream.
wios Supports the wios class from the old iostream library.
wstreampos Holds the current position of the buffer pointer or file pointer.
Manipulators
[edit | edit source]
Name description
boolalpha Specifies that variables of type bool appear as true or false in the stream.
dec Specifies that integer variables appear in base 10 notation.
fixed Specifies that a floating-point number is displayed in fixed-decimal notation.
hex Specifies that integer variables appear in base 16 notation.
internal Causes a number's sign to be left justified and the number to be right justified.
left Causes text that is not as wide as the output width to appear in the stream flush with the left margin.
noboolalpha Specifies that variables of type bool appear as 1 or 0 in the stream.
noshowbase Turns off indicating the notational base in which a number is displayed.
noshowpoint Displays only the whole-number part of floating-point numbers whose fractional part is zero.
noshowpos Causes positive numbers to not be explicitly signed.
noskipws Cause spaces to be read by the input stream.
nounitbuf Causes output to be buffered and processed when the buffer is full.
nouppercase Specifies that hexadecimal digits and the exponent in scientific notation appear in lowercase.
oct Specifies that integer variables appear in base 8 notation.
right Causes text that is not as wide as the output width to appear in the stream flush with the right margin.
scientific Causes floating point numbers to be displayed using scientific notation.
showbase Indicates the notational base in which a number is displayed.
showpoint Displays the whole-number part of a floating-point number and digits to the right of the decimal point even when the fractional part is zero.
showpos Causes positive numbers to be explicitly signed.
skipws Cause spaces to not be read by the input stream.
unitbuf Causes output to be processed when the buffer is not empty.
uppercase Specifies that hexadecimal digits and the exponent in scientific notation appear in uppercase.
Classes
[edit | edit source]
Name description
basic_ios The template class describes the storage and member functions common to both input streams (of template class basic_istream) and output streams (of template class basic_ostream) that depend on the template parameters.
fpos The template class describes an object that can store all the information needed to restore an arbitrary file-position indicator within any stream.
ios_base The class describes the storage and member functions common to both input and output streams that do not depend on the template parameters.

fstream

[edit | edit source]

With cout and cin, we can do basic communication with the user. For more complex io, we would like to read from and write to files. This is done with file stream classes, defined in the header <fstream>. ofstream is an output file stream, and ifstream is an input file stream.

Files

To open a file, one can either call open on the file stream or, more commonly, use the constructor. One can also supply an open mode to further control the file stream. Open modes include

  • ios::app Leaves the file's original contents and appends new data to the end.
  • ios::out Outputs new data in the file, removing the old contents. (default for ofstream)
  • ios::in Reads data from the file. (default for ifstream)

Example

// open a file called Test.txt and write "HELLO, HOW ARE YOU?" to it
#include <fstream>

using namespace std;

int main()
{
  ofstream file1;

  file1.open("file1.txt", ios::app);
  file1 << "This data will be appended to the file file1.txt\n";
  file1.close();

  ofstream file2("file2.txt");
  file2 << "This data will replace the contents of file2.txt\n";

  return 0;
}

The call to close() can be omitted, if you do not care about the return value (whether it succeeded); the destructors will call close when the object goes out of scope.

If an operation (e.g. opening a file) was unsuccessful, a flag is set in the stream object. You can check the flags' status using the bad() or fail() member functions, which return a boolean value. The stream object doesn't throw any exceptions in such a situation; hence manual status check is required. See reference for details on bad() and fail().

Text input until EOF/error/invalid input
[edit | edit source]

Input from the stream infile to a variable data until one of the following:

  • EOF reached on infile.
  • An error occurs while reading from infile (e.g., connection closed while reading from a remote file).
  • The input item is invalid, e.g. non-numeric characters, when data is of type int.
#include <iostream>

// …

while (infile >> data)
{
    // manipulate data here
}

Note that the following is not correct:

#include <iostream>

// …

while (!infile.eof())
{
    infile >> data; // wrong!
    // manipulate data here
}

This will cause the last item in the input file to be processed twice, because eof() does not return true until input fails due to EOF.

ostream

[edit | edit source]
Classes and output streams

It is often useful to have your own classes' instances compatible with the stream framework. For instance, if you defined the class Foo like this:

 class Foo
 {
 public:

	Foo() : m_iX(1), m_iY(2)
	{
	}

	int m_iX, m_iY;
 };

You will not be able to pass its instance to cout directly using the '<<' operator, because it is not defined for these two objects (Foo and ostream). What needs to be done is to define this operator and thus bind the user-defined class with the stream class.

 ostream& operator<<(ostream& output, Foo& arg)
 {
	output << arg.m_iX << "," << arg.m_iY;
	return output;
 }

Now this is possible:

 Foo myObject;
 cout << "my_object's values are: " << myObject << endl;

The operator function needs to have 'ostream&' as its return type, so chaining output works as usual between the stream and objects of type Foo:

 Foo my1, my2, my3;
 cout << my1 << my2 << my3;

This is because (cout << my1) is of type ostream&, so the next argument (my2) can be appended to it in the same expression, which again gives an ostream& so my3 can be appended and so on.

If you decided to restrict access to the member variables m_iX and m_iY (that is probably a good idea) within the class Foo, i.e.:

 class Foo
 {
 public:

	Foo() : m_iX(1), m_iY(2)
	{
	}

 private:
	int m_iX, m_iY;
 };

you will have trouble, because operator<< function doesn't have access to the private variables of its second argument. There are two possible solutions to this problem:

1. Within the class Foo, declare the operator<< function as the classes' friend that grants it access to private members, i.e. add the following line to the class declaration:

 
 friend ostream& operator<<(ostream& output, Foo& arg);

Then define the operator<< function as you normally would (note that the declared function is not a member of Foo, just its friend, so don't try defining it as Foo::operator<<).

2. Add public-available functions for accessing the member variables and make the operator<< function use these instead:

 class Foo
 {
 public:

	Foo() : m_iX(1), m_iY(2)
	{
	}

	int getX()
	{
		return m_iX;
	}

	int getY()
	{
		return m_iY;
	}

 private:
	int m_iX, m_iY;
 };

 ostream& operator<<(ostream& output, Foo& arg)
 {
	output << iArg.getX() << "," << iArg.getY();
	return output;
 }

‎Rounding number example

[edit | edit source]

This is a small example that rounds a number to a string, a function called RoundToString. Figures may have trailing zeros, those that would be expected to disappear using a number format.

The constant class contains repeating constants that should exist only once in the code so that to avoid inadvertent changes. (If the one constant is changed inadvertently, it is most likely to be seen, as it is used at several locations.)

The code was first cross-compiled by the JAVA TO C++ CONVERTER of Tangible Software Solutions. Parts may have a copyright notice requirement that prevents inclusion in this work you can get yourself the code for the StringConverter at that location.

Here is the relevant code and its call. You are invited to write a shorter version that gives the same result.

Common.cpp:

#include "StdAfx.h"

namespace common
{
    double const Common::NEARLY_ZERO = 1E-4;
    double const Common::VERY_LARGE = 1E10;
    string const Common::strZERO = *new string(1, Common::ZERO);
    
    bool Common::IsTrimmable(char const chCHARACTER,
        char const chTRIM,
        bool const bIS_NUMERIC)
    {
        return ((chCHARACTER == chTRIM)
            || (bIS_NUMERIC && (chCHARACTER == Common::ZERO)));
    }

    string const& Common::Trim(string const& strVALUE, char const chTRIM)
    {
        return TrimLeft(TrimRight(strVALUE, chTRIM), chTRIM);
    }

    string const& Common::TrimLeft(string const& strVALUE,
            char const chTRIM)
    {
        if (strVALUE.length() == 0) return strVALUE;
        else
        {
            ushort usPosition = 0;

            for (; usPosition < strVALUE.length(); usPosition++)
            {
                if (!IsTrimmable(strVALUE[usPosition], chTRIM)) break;
            }

            return *new string(strVALUE.substr(usPosition));
        }
    }

    string const& Common::TrimRight(string const& strVALUE,
        char const chTRIM)
    {
        if (strVALUE.length() == 0) return strVALUE;
        else
        {
            ushort usPosition = strVALUE.length() - 1;

            for (; usPosition < strVALUE.length(); usPosition--)
            {
                if (!IsTrimmable(strVALUE[usPosition], chTRIM))
                {
                    if (strVALUE[usPosition] != Common::PERIOD) ++usPosition;

                    break;
                }
            }

            return *new string(strVALUE.substr(0, usPosition));
        }
    }
}

Common.h:

#pragma once

#include <string>

namespace common
{
    /// <summary>
    /// Class that comprises of constant values and recurring algorithms.
    /// 
    /// @author Saban
    /// 
    ///</summary>
    class Common
    {
        /// <summary>
        /// Determines, if the character is trimmable or not.
        /// </summary>
        /// <param name="chCHARACTER">Character to be checked</param>
        /// <param name="chTRIM">
        /// Trim character that defaults to a space
        /// </param>
        /// <param name="bIS_NUMERIC">
        /// If numeric, zeros are also considered as trimmable characters
        /// </param>
        /// <returns>Whether the character is trimmable or not</returns>
        static bool IsTrimmable(char const chCHARACTER,
            char const chTRIM = SPACE, bool const bIS_NUMERIC = true);

    public:
        /// <summary>Carriage return constant</summary>
        //static char const CARRIAGE_RETURN = '\r';
        /// <summary>Constant of comma or decimal point in German</summary>
        static char const COMMA = ',';
        /// <summary>Dash or minus constant</summary>
        static char const DASH = '-';
        /// <summary>
        /// The exponent sign in a scientific number, or the letter e.
        /// </summary>
        static char const EXPONENT = 'e';
        /// <summary>The full stop or period</summary>
        static char const PERIOD = '.';
        /// <summary>Space constant</summary>
        static char const SPACE = ' ';
        /// <summary>Space constant</summary>
        static char const ZERO = '0';
        /// <summary>
        //// Value under which the double should switch to fixed-point.
        /// </summary>
        static double const VERY_LARGE;
        /// <summary>
        //// Value above which the double should switch to fixed-point.
        /// </summary>
        static double const NEARLY_ZERO;
          /// <summary>
          /// The zero string constant used at several places
        /// </summary>
          static string const strZERO;

        /// <summary>
        /// Trims the trim character from left and right of the value.
        /// </summary>
        /// <param name="strVALUE">Value to be trimmed</param>
        /// <param name="chTRIM">
        /// Trim character that defaults to a space
        /// </param>
        /// <returns>Trimmed string</returns>
        static string const& Trim(string const& strVALUE,
            char const chTRIM = Common::SPACE);

        /// <summary>
        /// Trims the trim character from left the value.
        /// </summary>
        /// <param name="strVALUE">Value to be trimmed</param>
        /// <param name="chTRIM">
        /// Trim character that defaults to a space
        /// </param>
        /// <returns>Trimmed string</returns>
        static string const& TrimLeft(string const& strVALUE,
            char const chTRIM = Common::SPACE);

        /// <summary>
        /// Trims the trim character from right of the value.
        /// </summary>
        /// <param name="strVALUE">Value to be trimmed</param>
        /// <param name="chTRIM">
        /// Trim character that defaults to a space
        /// </param>
        /// <returns>Trimmed string</returns>
        static string const& TrimRight(string const& strVALUE,
            char const chTRIM = Common::SPACE);
    }; // class Common
}

The Math class is an enhancement to the <math.h> library and contains the rounding calculations.

Math.cpp:

#include "StdAfx.h"
#include <string>

namespace common
{
    string const Maths::strZEROS = "000000000000000000000000000000000";

    byte Maths::CalculateMissingSignificantZeros(
        byte const ySIGNIFICANTS_AFTER,
        char const chSEPARATOR,
        double const dVALUE,
        string const strMANTISSA)
    {
        // Existing significants after decimal separator are
        byte const yAFTER = FindSignificantsAfterDecimal(chSEPARATOR, strMANTISSA);
        // Number of digits to add are
        byte const yZEROS = ySIGNIFICANTS_AFTER - ((yAFTER == 0) ? 1 : yAFTER);

        return ((yZEROS >= 0) ? yZEROS : 0);
    }

    byte Maths::FindDecimalSeparatorPosition(string const& strVALUE)
    {
        byte const ySEPARATOR_AT = (byte)strVALUE.find(Common::PERIOD);

        return (ySEPARATOR_AT > -1)
            ? ySEPARATOR_AT : (byte)strVALUE.find(Common::COMMA);
    }

    byte Maths::FindFirstNonZeroDigit(double const dVALUE)
    {
        return FindFirstNonZeroDigit(StringConverter::ToString
            <double, StringConverter::DIGITS>(dVALUE));
    }

    byte Maths::FindFirstNonZeroDigit(string const& strVALUE)
    {
        // Find the position of the first non-zero digit:
        byte yNonZeroAt = 0;

        for (; (yNonZeroAt < (byte)strVALUE.length())
            && ((strVALUE[yNonZeroAt] == Common::DASH)
            || (strVALUE[yNonZeroAt] == Common::PERIOD)
            || (strVALUE[yNonZeroAt] == Common::ZERO)); yNonZeroAt++) ;

        return yNonZeroAt;
    }

    byte Maths::FindSignificantDigits(byte const ySIGNIFICANTS_AFTER,
        char const chSEPARATOR,
        double const dVALUE)
    {
        if (dVALUE == 0) return 0;
        else
        {
//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
            string strMantissa = FindMantissa(TestCommons::SIGNIFICANTS,
                chSEPARATOR, StringConverter::ToString<double,
                StringConverter::DIGITS>(dVALUE));

            if (dVALUE == static_cast<long>(dVALUE))
            {
                strMantissa =
                    strMantissa.substr(0, strMantissa.find(Common::COMMA));
            }

            strMantissa = RetrieveDigits(chSEPARATOR, strMantissa);

            return strMantissa.substr(
                FindFirstNonZeroDigit(strMantissa)).length();
        }
    }

    byte Maths::FindSignificantsAfterDecimal(byte const ySIGNIFICANTS_BEFORE,
        byte const ySIGNIFICANT_DIGITS)
    {
        byte const yAFTER_DECIMAL = ySIGNIFICANT_DIGITS - ySIGNIFICANTS_BEFORE;

        return (yAFTER_DECIMAL > 0) ? yAFTER_DECIMAL : 0;
    }

    byte Maths::FindSignificantsAfterDecimal(char const chSEPARATOR,
        double const dVALUE)
    {
        if (dVALUE == 0) return 1;
        else
        {
//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
            string strValue = StringConverter::ToString<double,
                StringConverter::DIGITS>(dVALUE);

            byte const ySEPARATOR_AT = (byte)strValue.find(chSEPARATOR);

            if (ySEPARATOR_AT > -1)
            {
                strValue = strValue.substr(ySEPARATOR_AT + 1);
            }

            short const sE_AT = strValue.find(Common::EXPONENT);

            if (sE_AT > 0) strValue = strValue.substr(0, sE_AT);

            long lValue = StringConverter::FromString
                <long, StringConverter::DIGITS>(strValue);

            if (abs(dVALUE) < 1)
            {
                return (byte)StringConverter::ToString<long,
                    StringConverter::DIGITS>(lValue).length();
            }
            else if (lValue == 0) return 0;
            else
            {
                strValue = "0." + strValue;

                return (byte)(strValue.length() - 2);
            }
        }
    }

    byte Maths::FindSignificantsBeforeDecimal(char const chSEPARATOR,
        double const dVALUE)
    {
        string const strVALUE = StringConverter::ToString<double,
            StringConverter::DIGITS>(dVALUE);

        // Return immediately, if result is clear: Special handling at
        // crossroads of floating point and exponential numbers:
        if ((dVALUE == 0)
            || (abs(dVALUE) >= Common::NEARLY_ZERO) && (abs(dVALUE) < 1))
        {
            return 0;
        }
        else if ((abs(dVALUE) > 0) && (abs(dVALUE) < Common::NEARLY_ZERO))
        {
            return 1;
        }
        else
        {
            byte significants = 0;
            // Significant digits to the right of decimal separator:
            for (byte s = 0; s < (byte)strVALUE.length(); s++)
            {
                if ((strVALUE[s] == chSEPARATOR)
                    || (strVALUE[s] == Common::EXPONENT))
                {
                    break;
                }
                else if (strVALUE[s] != Common::DASH) significants++;
            }

            return significants;
        }
    }

    byte Maths::FindSignificantsAfterDecimal(char const chSEPARATOR,
        string const strVALUE)
    {
        size_t const COMMA_AT = strVALUE.find(chSEPARATOR);
        size_t const LENGTH = strVALUE.length();
        // Existing digits after decimal separator are
        byte yAfter = 0;
        // Existing significants after decimal separator may start at the first
        // non-zero digit:
        if (StringConverter::FromString<double, 5>
            (strVALUE.substr(0, COMMA_AT)) == 0)
        {
            string strRightOf = Common::TrimLeft(strVALUE.substr(COMMA_AT + 1));

            yAfter = strRightOf.length();
        }
        else yAfter = (COMMA_AT < string::npos) ? LENGTH - 1 - COMMA_AT : 0;

        return yAfter;
    }

    double Maths::Power(short const sBASIS, short const sEXPONENT)
    {
        if (sBASIS == 0) return (sEXPONENT != 0) ? 1 : 0;
        else
        {
            if (sEXPONENT == 0) return 1;
            else
            {
                // The Math method power does change the least significant 
                // digits after the decimal separator and is therefore useless.
                double result = 1;

                if (sEXPONENT > 0)
                {
                    for (short s = 0; s < sEXPONENT; s++) result *= sBASIS;
                }
                else if (sEXPONENT < 0)
                {
                    for (short s = sEXPONENT; s < 0; s++) result /= sBASIS;
                }

                return result;
            }
        }
    }

    double Maths::Round(byte const yDIGITS,
        char const chSEPARATOR,
        double const dVALUE)
    {
        if (dVALUE == 0) return 0;
        else
        {
            bool bIsScientific = false;
            double const dCONSTANT = Power(10, yDIGITS);

            if ((abs(dVALUE) < Common::NEARLY_ZERO)
                || (abs(dVALUE) >= Common::VERY_LARGE))
            {
                bIsScientific = true;
            }
            
            short const sEXPONENT =
                FindExponent(dVALUE, chSEPARATOR, bIsScientific);

            short sExponent = sEXPONENT;

            // Determine the correcting power:
            short sPower = sExponent;

            if (sEXPONENT == 0)
            {
                sPower = FindExponent(dVALUE, chSEPARATOR, HasDecimals(dVALUE));
            }

            double dValue1 = dVALUE*dCONSTANT*pow(10., -sPower);

            string const strE_SIGN = (sExponent < 0)
                ? StringConverter::ToString<char,
                StringConverter::DIGITS>(Common::DASH) : "";

            if (sExponent != 0)
            {
                sExponent = static_cast<short>(abs(sExponent));
                dValue1 = Round(dValue1);
            }
            else dValue1 = Round(dValue1)/dCONSTANT/pow(10., -sPower);

            // Power method cannot be used, as the exponentiated number may
            // exceed the maximal long value.
            sExponent -= Signum(sEXPONENT)*(FindSignificantDigits(
                yDIGITS, chSEPARATOR, dValue1) - 1);

            if (sEXPONENT != 0)
            {
//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
                string strValue = StringConverter::ToString<double,
                    StringConverter::DIGITS>(dValue1);

//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
                strValue =
                    strValue.substr(0, FindDecimalSeparatorPosition(strValue))
                    + Common::EXPONENT + strE_SIGN
                    + StringConverter::ToString<short,
                    StringConverter::DIGITS>(sExponent);

                dValue1 = StringConverter::FromString<double, 5>(strValue);
            }

            return dValue1;
        }
    }

    double Maths::Round(double const dValue)
    {
        return (double)(long long)(dValue + .5);
    }

    short Maths::FindExponent(double const dVALUE,
        char const chSEPARATOR,
        bool const bSCIENTIFIC)
    {
//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
        return (short)StringConverter::FromString<short,
            StringConverter::DIGITS>(FindExponent(StringConverter::ToString
            <double, StringConverter::DIGITS>(dVALUE), chSEPARATOR,
            bSCIENTIFIC));
    }

    string Maths::FindExponent(string const& strVALUE,
        char const chSEPARATOR,
        bool const bSCIENTIFIC)
    {
        if (StringConverter::FromString
            <double, StringConverter::DIGITS>(strVALUE) == 0)
        {
            return Common::strZERO;
        }

        short const sE_AT = strVALUE.find(Common::EXPONENT);
        short sExponent = 0;

        if (sE_AT < 0)
        {
            // If all numbers are to be considered scientific, such as
            // 1 = 1.0000e0…
            if (bSCIENTIFIC)
            {
                // Find the exponent by counting leading zeros:
                byte const ySEPARATOR_AT = strVALUE.find(chSEPARATOR);

                if (ySEPARATOR_AT > -1)
                {
                    string const strAFTER = strVALUE.substr(ySEPARATOR_AT + 1);
                    sExponent = 0;

                    for (; sExponent < (short)strAFTER.length(); sExponent++)
                    {
                        if ((strAFTER[sExponent] >= '1')
                            && (strAFTER[sExponent] <= '9'))
                        {
                            sExponent *= -1;
                            break;
                        }
                    }
                }
            }
            else return Common::strZERO;
        }
        else
        {
            sExponent = (short)StringConverter::FromString
                <double, StringConverter::DIGITS>(strVALUE.substr(sE_AT + 1));
        }

        return StringConverter::ToString<short,
            StringConverter::DIGITS>(sExponent);
    }

    string Maths::FindMantissa(byte const yDIGITS,
        char const chSEPARATOR,
        const string& strVALUE)
    {
        byte yDigits = yDIGITS;
        short const sE_AT = strVALUE.find(Common::EXPONENT);
        string strValue = strVALUE;

        // Remove lagging insignificant zeros, if any:
        if (sE_AT == -1)
        {
            if (StringConverter::FromString<short,
                3>(strValue.substr(0, 2)) == 0)
            {
                byte yPosition = 2;

                for (; (yPosition < (byte)strValue.length())
                    && ((strValue[yPosition] == Common::PERIOD)
                    || (strValue[yPosition] == Common::ZERO)); yPosition++);

                yDigits += yPosition;

                strValue = strValue.substr(0, yDigits);
            }
        }
        else strValue = Common::TrimRight(strValue.substr(0, sE_AT));

        if (StringConverter::FromString<double, StringConverter::DIGITS>(strValue) == 0)
        {
            strValue = RemoveInsignificants(yDIGITS, strValue);
        }
        else strValue = RemoveInsignificants(yDigits, strValue);

        if (FindDecimalSeparatorPosition(strValue) == -1)
        {
            return strValue + ".0";
        }
        else return strValue;
    }

    string Maths::RemoveInsignificants(byte const yDIGITS,
        string const& strVALUE)
    {
        byte const yCHARACTERS = yDIGITS
            + ((FindDecimalSeparatorPosition(strVALUE) < string::npos) ? 1 : 0)
            + ((strVALUE[0] == Common::DASH)
            ? ((strVALUE[1] == Common::ZERO) ? 2 : 1)
            : ((strVALUE[0] == Common::ZERO) ? 1 : 0));

        return strVALUE.substr(0, yCHARACTERS);
    }

    string Maths::RetrieveDigits(char const chSEPARATOR, const string& strNUMBER)
    {
        string strNumber = strNUMBER;

        short const sE_AT = strNumber.find(Common::EXPONENT);
        // Strip off exponent part, if it exists:
        if (sE_AT > -1) strNumber = strNumber.substr(0, sE_AT);

//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'replace':
        return StringConverter::Replace(StringConverter::Replace(strNumber,
            StringConverter::ToString<char, 1>(Common::DASH), ""),
            StringConverter::ToString<char, 1>(chSEPARATOR), "");
    }

    string Maths::RoundToString(byte const ySIGNIFICANT_DIGITS,
        char const chSEPARATOR,
        double dValue)
    {
        // Number of significants that *are* before the decimal separator:
//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
        byte const ySIGNIFICANTS_BEFORE =
            FindSignificantsBeforeDecimal(chSEPARATOR, dValue);
        // Number of decimals that *should* be after the decimal separator:
        byte const ySIGNIFICANTS_AFTER = FindSignificantsAfterDecimal(
            ySIGNIFICANTS_BEFORE, ySIGNIFICANT_DIGITS);

        byte const yDIGITS = (dValue != 0)
            ? ySIGNIFICANTS_BEFORE + ySIGNIFICANTS_AFTER : 3 /* = 0.0 */;
        // Round to the specified number of digits after decimal separator:
        double const dROUNDED =
            Maths::Round(ySIGNIFICANTS_AFTER, chSEPARATOR, dValue);

//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
        string const strEXPONENT = FindExponent(StringConverter::ToString
            <double, StringConverter::DIGITS>(dROUNDED));
//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
        string const strMANTISSA = FindMantissa(TestCommons::SIGNIFICANTS,
            chSEPARATOR, StringConverter::ToString<double,
            StringConverter::DIGITS>(dROUNDED));

        double const dMANTISSA = StringConverter::FromString
            <double, TestCommons::SIGNIFICANTS>(strMANTISSA);
        StringBuilder* pRESULT = new StringBuilder(strMANTISSA);

        // Determine the significant digits in this number:
        byte const ySIGNIFICANTS = FindSignificantDigits(ySIGNIFICANTS_AFTER,
            chSEPARATOR, dMANTISSA);
        // Add lagging zeros, if necessary:
        if (ySIGNIFICANTS <= ySIGNIFICANT_DIGITS)
        {
            if (ySIGNIFICANTS_AFTER != 0)
            {
                if (dValue != 0)
                {
                    pRESULT->Append(strZEROS.substr(0,
                        CalculateMissingSignificantZeros(ySIGNIFICANTS_AFTER,
                        chSEPARATOR, dMANTISSA, strMANTISSA)));
                }
            }
            else
            {
                // Cut off the decimal separator & after decimal digits:
//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
                byte const yDECIMAL =
                    pRESULT->Find(StringConverter::ToString<char,
                    StringConverter::DIGITS>(chSEPARATOR));

                if (yDECIMAL > -1) pRESULT->SetLength(yDECIMAL);
            }
        }
        else if (ySIGNIFICANTS_BEFORE > ySIGNIFICANT_DIGITS)
        {
            dValue /= Power(10, ySIGNIFICANTS_BEFORE - ySIGNIFICANT_DIGITS);

            dValue = Round(dValue);

            byte const yDIGITS = ySIGNIFICANT_DIGITS + ((dValue < 0) ? 1 : 0);
//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
            string const strVALUE = StringConverter::ToString<double,
                StringConverter::DIGITS>(dValue).substr(0, yDIGITS);
            pRESULT->SetLength(0);

            pRESULT->Append(strVALUE + strZEROS.substr(0,
                ySIGNIFICANTS_BEFORE - ySIGNIFICANT_DIGITS));
        }

        if (StringConverter::FromString<double,
            StringConverter::DIGITS>(strEXPONENT) != 0)
        {
            pRESULT->Append(Common::EXPONENT + strEXPONENT);
        }

//JAVA TO C++ CONVERTER TODO TASK: No native C++ equivalent to 'ToString':
        return pRESULT->ToString();
    } // public static String RoundToString(…)
}

Math.h:

#pragma once

#include <string>
#include <cmath>

/// 
namespace common
{
    /// <summary>
    /// Class for special mathematical calculations.
    /// ATTENTION: Should not depend on any other class except Java libraries!
    /// @author Saban
    ///</summary>
    class Maths
    {
    private:
        /// <summary>The string of zeros</summary>
        static string const strZEROS;

        /// <summary>
        /// Determines how many zeros are to be appended after the decimal
        /// digits.
        /// </summary>
        /// <param name="ySIGNIFICANTS_AFTER">
        /// Requested significant digits after decimal
        /// </param>
        /// <param name="chSEPARATOR">
        /// Language-specific decimal separator
        /// </param>
        /// </param>
        /// <param name="dVALUE">Rounded number</param>
        /// <param name="strMANTISSA">
        /// Current string where missing digits are to be determined
        /// </param>
        /// <returns>Requested value</returns>
        static byte CalculateMissingSignificantZeros(
            byte const ySIGNIFICANTS_AFTER, char const chSEPARATOR,
            double const dVALUE,
            string const strMANTISSA = "");

        /// <summary>
        /// Finds the decimal position language-independently.
        /// </summary>
        /// <param name="strVALUE">
        /// Value to be searched for the decimal separator
        /// </param>
        /// <returns>
        /// The position of the decimal separator or string::npos,
        /// if no decimal separator has been found.
        /// </returns>
        static byte FindDecimalSeparatorPosition(string const& strVALUE);

        /// <summary>
        /// Finds the first non-zero decimal position.
        /// </summary>
        /// <param name="dVALUE">
        /// Value to be searched for the decimal position
        /// </param>
        /// <returns>The first non-zero decimal position</returns>
        static byte FindFirstNonZeroDigit(double const dVALUE);

        /// <summary>
        /// Finds the first non-zero decimal position.
        /// </summary>
        /// <param name="strVALUE">
        /// Value to be searched for the decimal position
        /// </param>
        /// <returns>The first non-zero decimal position</returns>
        static byte FindFirstNonZeroDigit(string const& strVALUE);

        /// <summary>
        /// Calculates the number of all significant digits (without the sign
        /// and the decimal separator).
        /// </summary>
        /// <param name="ySIGNIFICANTS_AFTER">
        /// Number of decimal places after the separator</param>
        /// <param name="chSEPARATOR">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="dVALUE">
        /// Value where the digits are to be counted
        /// </param>
        /// <returns>Number of significant digits</returns>
        static byte FindSignificantDigits(byte const ySIGNIFICANTS_AFTER,
            char const chSEPARATOR, double const dVALUE);

        /// <summary>
        /// Determines the number of significant digits after the decimal
        /// separator knowing the total number of significant digits and the
        /// number before the decimal separator.
        /// </summary>
        /// <param name="ySIGNIFICANTS_BEFORE">
        /// Number of significant digits before separator
        /// </param>
        /// <param name="ySIGNIFICANT_DIGITS">
        /// Number of all significant digits
        /// </param>
        /// Number of significant decimals after the separator
        /// </returns>
        static byte FindSignificantsAfterDecimal(
            byte const ySIGNIFICANTS_BEFORE, byte const ySIGNIFICANT_DIGITS);

        /// <summary>
        /// Finds the significant digits after the decimal separator of a
        /// mantissa.
        /// </summary>
        /// <param name="chSEPARATOR">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="dVALUE">Value to be scrutinised</param>
        /// <returns>
        /// Number of insignificant zeros after decimal separator.
        /// </returns>
        static byte FindSignificantsAfterDecimal(char const chSEPARATOR,
            double const dVALUE);

        /// <summary>
        /// Finds the significant digits after the decimal separator of a
        /// mantissa.
        /// </summary>
        /// <param name="chSEPARATOR">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="strVALUE">Value to be scrutinised</param>
        /// <returns>
        /// Number of insignificant zeros after decimal separator.
        /// </returns>
        static byte FindSignificantsAfterDecimal(char const chSEPARATOR,
            string const strVALUE);

        /// <summary>
        /// Determines the number of digits before the decimal point.</summary>
        /// <param name="chSEPARATOR">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="dVALUE">Value to be scrutinised</param>
        /// <returns>Number of digits before the decimal separator</returns>
        static byte FindSignificantsBeforeDecimal(char const chSEPARATOR,
            double const dVALUE);

        /// <summary>
        /// Returns the exponent part of the double number.</summary>
        /// <param name="dVALUE">
        /// Value of which the exponent is of interest
        /// </param>
        /// <param name="chSEPARATOR">Decimal separator</param>
        /// <param name="bSCIENTIFIC">
        /// If true, the number is considered in scientific notation of the form
        /// 9.999e999 (like 1 = 1.0e0 or 0.124 = 1.24e-1).
        /// </param>
        /// <returns>Exponent of the number or zero.</returns>
        static short FindExponent(double const dVALUE,
            char const chSEPARATOR = Common::PERIOD,
            bool const bSCIENTIFIC = false);

        /// <summary>
        /// Finds the exponent of a number.</summary>
        /// <param name="strVALUE">
        /// Value where an exponent is to be searched
        /// </param>
        /// <param name="chSEPARATOR">Decimal separator</param>
        /// <param name="bSCIENTIFIC">
        /// If true, the number is considered in scientific notation of the form
        /// 1 = 1.0e0 or 0.124 = 1.24e-1.
        /// </param>
        /// <returns>Exponent, if it exists, or "0"</returns>
        static string FindExponent(string const& strVALUE,
            char const chSEPARATOR = Common::PERIOD,
            bool const bSCIENTIFIC = false);

        /// <summary>
        /// Finds the mantissa of a number.</summary>
        /// <param name="yDIGITS">
        /// Number of all digits
        /// </param>
        /// <param name="chSEPARATOR">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="strVALUE">
        /// Value where the mantissa is to be found
        /// </param>
        /// <returns>Mantissa of the number</returns>
        static string FindMantissa(byte const yDIGITS,
            char const chSEPARATOR,
            string const& strVALUE);

        /// <summary>
        /// Removes all insignificant digits.</summary>
        /// <param name="yDIGITS">
        /// Number of significant digits
        /// </param>
        /// <returns>Number with the requested number of digits</returns>
        static string RemoveInsignificants(byte const yDigits,
            string const& strVALUE);

        /// <summary>
        /// Retrieves the digits of the value without decimal separator or
        /// sign.
        /// </summary>
        /// <param name="chSEPARATOR"></param>
        /// <param name="strNUMBER">Mantissa to be scrutinised</param>
        /// <returns>The digits only</returns>
        static string RetrieveDigits(char const chSEPARATOR,
            string const& strNUMBER);

    public:
        /// <summary>
        /// Determines whether the number has decimal places after 
        /// the separator or not.
        /// </summary>
        /// <param name="VALUE"></param>
        /// <returns>true, if it has decimals and false otherwise.</returns>
        template<class T> 
        static bool HasDecimals(const T VALUE)
        {
            return ((VALUE - (long long)VALUE) != 0);
        }

        /// <summary>
        /// Calculates the power of the base to the exponent without changing
        /// the least-significant digits of a number.
        /// </summary>
        /// <param name="BASIS"></param>
        /// <param name="EXPONENT"></param>
        /// <returns>BASIS to power of EXPONENT</returns>
        static double Power(short const sBASIS, short const sEXPONENT);

        /// <summary>
        /// Rounds a number to the decimal places.</summary>
        /// <param name="yDIGITS">Number of all decimal places</param>
        /// <param name="chSEPARATOR">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="dVALUE">Number to be rounded</param>
        /// <returns>Rounded number to the requested decimal places</returns>
        static double Round(byte const yDIGITS,
            char const chSEPARATOR, double const dVALUE);

        /// <summary>
        /// Replacement for Math.round(double) of Java.</summary>
        /// <param name="dValue">Number to be rounded</param>
        /// <returns>Rounded number to the requested decimal places</returns>
        static double Round(double const dVALUE);

        /// <summary>Signum function</summary>
        /// <param name="number">Value to be scrutinised</param>
        /// <returns>Sign of the number</returns>
        template<class T> 
        static byte Signum(T number) 
        {
            return (number < T(0)) ? T(-1) : (number > T(0));
        }

        /// <summary>
        /// Rounds to a fixed number of significant digits.</summary>
        /// <param name="ySIGNIFICANT_DIGITS">
        /// Requested number of significant digits
        /// </param>
        /// <param name="chSEPARATOR">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="dValue">Number to be rounded</param>
        /// <returns>Rounded number</returns>
        static string RoundToString(byte const ySIGNIFICANT_DIGITS,
            char const chSEPARATOR, double dValue);
    }; // class Maths
}

Using precompiled headers requires the StdAfx files:

StdAfx.cpp:

// StdAfx.cpp : Quelldatei, die nur die Standard-Includes einbindet.
// Commons.pch ist der vorkompilierte Header.
// StdAfx.obj enthält die vorkompilierten Typinformationen.

#include "StdAfx.h"

StdAfx.h:

// StdAfx.h : Includedatei für Standardsystem-Includedateien
// oder häufig verwendete projektspezifische Includedateien,
// die nur in unregelmäßigen Abständen geändert werden.
//

#pragma once

using namespace std;

typedef signed char byte;
typedef unsigned short ushort;

// Used headers:
#include "Common.h"
#include "Maths.h"
#include "StringBuilder.h"
#include "TestCommons.h"

#include "StringConverter.h"

#include <iostream>

The StringBuilder class was added by the JAVA TO C++ CONVERTER during the crosscompilation:

StringBuilder.cpp:

#include "StdAfx.h"

namespace common
{
    StringBuilder::StringBuilder()
    {
        strMain = "";
    }
    
    StringBuilder::StringBuilder(string const& strVALUE)
    {
        Append(strVALUE);
    }
    
    size_t const StringBuilder::Find(string const& strSEARCH) const
    {
        return strMain.find(strSEARCH);
    }
 
    string const& StringBuilder::ToString() const
    {
        return strMain; 
    }

    void StringBuilder::Append(string const& strVALUE)
    {
        strMain.append(strVALUE);
    }

    void StringBuilder::SetLength(const string::size_type SIZE)
    {
        strMain.resize(SIZE);
    }
}

StringBuilder.h:

#pragma once

namespace common
{
    class StringBuilder
    {
    private: 
        string strMain; 

    public:
        /// <summary>
        /// Standard constructor
        /// </summary>
        StringBuilder();

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="strSUBJECT">Value to be used</param>
        StringBuilder(string const& strSUBJECT);

        /// <summary>
        /// Finds the search string inside itself.
        /// </summary>
        /// <param name="strSEARCH">Value to be used</param>
        /// <returns>
        /// The position of the searched text or -1, if the search string
        /// has not been found.
        /// </returns>
        size_t const Find(string const& strSEARCH) const;

        /// <summary>
        /// Converts the contents of itself to a string.
        /// </summary>
        /// <returns>String content</returns>
        string const& ToString() const;

        /// <summary>
        /// Appends a text to this object
        /// </summary>
        /// <param name="strVALUE">Value to be appended</param>
        void Append(string const& strVALUE);

        /// <summary>
        /// Sets the length of the content of this object.
        /// </summary>
        /// <param name="SIZE">New reduced size</param>
        void SetLength(const string::size_type SIZE);
    };
}

Extensive testing of a software is crucial for qualitative code. To say that the code is tested does not give much information. The question is what is tested. Not in this case, but often it is also important to know where (in which environment) it was tested, and how - i.e. the test succession. Here is the code used to test the Maths class.

TestCommons.cpp:

#include "StdAfx.h"


namespace common
{
    void TestCommons::Test()
    {
        // Test rounding
        vector<double>* pa_dValues = new vector<double>();

        vector<double>& a_dValues = *pa_dValues;

        a_dValues.push_back(0.0);
        AddValue(1.4012984643248202e-45, a_dValues);
        AddValue(1.999999757e-5, a_dValues);
        AddValue(1.999999757e-4, a_dValues);
        AddValue(0.000640589, a_dValues);
        AddValue(1.999999757e-3, a_dValues);
        AddValue(0.3396899998188019, a_dValues);
        AddValue(0.34, a_dValues);
        AddValue(7.07, a_dValues);
        AddValue(118.188, a_dValues);
        AddValue(118.2, a_dValues);
        AddValue(123.405009, a_dValues);
        AddValue(30.76994323730469, a_dValues);
        AddValue(130.76994323730469, a_dValues);
        AddValue(540, a_dValues);
        AddValue(12345, a_dValues);
        AddValue(123456, a_dValues);
        AddValue(540911, a_dValues);
        AddValue(9.223372036854776e56, a_dValues);

        byte const ySIGNIFICANTS = 5;

        for (vector<double>::const_iterator element = a_dValues.begin();
            element != a_dValues.end(); ++element)
        {
            cout << "Maths::RoundToString(" << (short)ySIGNIFICANTS << ", '"
                << Common::PERIOD << "', " << StringConverter::ToString
                <double, StringConverter::DIGITS>(*element) << ") = ";
            cout << Maths::RoundToString(ySIGNIFICANTS, Common::PERIOD,
                *element) << endl;
        }

        pa_dValues->clear();
        byte y;

        cin >> y;
    } // void Test()

    void TestCommons::AddValue(double const dVALUE, vector<double>& a_dValues)
    {
        a_dValues.push_back(-dVALUE);
        a_dValues.push_back(dVALUE);
    }
}

TestCommons.h:

#pragma once

#include <string>
#include <vector>

namespace common
{
    /// <summary>
    /// Test class for the common functionality
    /// @author Saban
    ///</summary>
    class TestCommons
    {
    private:
        /// <summary>
        /// Method that adds a negative and a positive value to values.</summary>
        /// <param name="dVALUE"></param>
        /// <param name="a_dValues"></param>
        static void AddValue(double const dVALUE, vector<double>& a_dValues);

    public:
        /// <summary>Number of significant digits</summary>
        static short const SIGNIFICANTS = 5;

        /// <summary>
        /// Test for the common functionality</summary>
        /// <param name="args"></param>
        static void Test();
    }; // class TestCommons
}

The results of your better code should comply with the result I got:

Maths::RoundToString(5, '.', 0.00000000000000000) = 0.00000
Maths::RoundToString(5, '.', -1.40129846432482020e-045) = -1.4012e-45
Maths::RoundToString(5, '.', 1.40129846432482020e-045) = 1.4013e-45
Maths::RoundToString(5, '.', -1.99999975700000000e-005) = -1.9998e-5
Maths::RoundToString(5, '.', 1.99999975700000000e-005) = 2.0000e-5
Maths::RoundToString(5, '.', -0.00019999997570000) = -0.00019999
Maths::RoundToString(5, '.', 0.00019999997570000) = 0.00020000
Maths::RoundToString(5, '.', -0.00064058900000000) = -0.00064058
Maths::RoundToString(5, '.', 0.00064058900000000) = 0.00064059
Maths::RoundToString(5, '.', -0.00199999975700000) = -0.0019999
Maths::RoundToString(5, '.', 0.00199999975700000) = 0.0020000
Maths::RoundToString(5, '.', -0.33968999981880188) = -0.33967
Maths::RoundToString(5, '.', 0.33968999981880188) = 0.33968
Maths::RoundToString(5, '.', -0.34000000000000002) = -0.33999
Maths::RoundToString(5, '.', 0.34000000000000002) = 0.34000
Maths::RoundToString(5, '.', -7.07000000000000030) = -7.0699
Maths::RoundToString(5, '.', 7.07000000000000030) = 7.0700
Maths::RoundToString(5, '.', -118.18800000000000000) = -118.18
Maths::RoundToString(5, '.', 118.18800000000000000) = 118.19
Maths::RoundToString(5, '.', -118.20000000000000000) = -118.19
Maths::RoundToString(5, '.', 118.20000000000000000) = 118.20
Maths::RoundToString(5, '.', -123.40500900000001000) = -123.40
Maths::RoundToString(5, '.', 123.40500900000001000) = 123.41
Maths::RoundToString(5, '.', -30.76994323730469100) = -30.768
Maths::RoundToString(5, '.', 30.76994323730469100) = 30.770
Maths::RoundToString(5, '.', -130.76994323730469000) = -130.75
Maths::RoundToString(5, '.', 130.76994323730469000) = 130.77
Maths::RoundToString(5, '.', -540.00000000000000000) = -539.99
Maths::RoundToString(5, '.', 540.00000000000000000) = 540.00
Maths::RoundToString(5, '.', -12345.00000000000000000) = -12344
Maths::RoundToString(5, '.', 12345.00000000000000000) = 12345
Maths::RoundToString(5, '.', -123456.00000000000000000) = -123450
Maths::RoundToString(5, '.', 123456.00000000000000000) = 123460
Maths::RoundToString(5, '.', -540911.00000000000000000) = -540900
Maths::RoundToString(5, '.', 540911.00000000000000000) = 540910
Maths::RoundToString(5, '.', -9.22337203685477560e+056) = -9.2232e56
Maths::RoundToString(5, '.', 9.22337203685477560e+056) = 9.2234e56

If you are interested in a comparison of C++ with C#, take a look at C# programming rounding number example. If you want to compare C++ with Java, compare it to the rounding code at Java Programming rounding number example.