I have some code which prints some small numbers (actually years) and the request is to have the numbers printed as Roman numerals instead of using the usual Hindu-Arabic numerals:
int main() {
// do something to make all integers appear in Roman numerals
std::cout << "In the year " << 2013 << " the following output was generated:\n";
// ...
}
What can be done to format int
s as Roman numerals?
There are two separate parts to the question:
int
into a sequence of characters with the Roman representation of the value.int
and turn it into the sequence just described.The Roman numerals follow a fairly straight forward rule which seems to be handled easiest with a simple look-up table. Since the main focus of the question is on how to make it work with IOStreams, a straight forward algorithm is used:
Each "digit" is simply produced by looking up the corresponding string and copying it to an iterator. If the integer is out of range for the value which can be represented using Roman numerals an exception is thrown. The longest string which can be produced is 15 characters long (3888).
The next step is to setup
std::cout
such that it formatsint
s using the above conversion. When anstd::ostream
needs to convert any of the built-in numeric types (integers, floating points), or the typesbool
andvoid const*
, it obtains thestd::num_put<cT>
facet from the stream'sstd::locale
and callsput()
on the object, essentially usingBy deriving from
std::num_put<char>
and overriding thedo_put()
member function for the version taking along
as argument, the formatting of the numbers can be changed:Although the function is relatively long it is fairly straight forward:
v
is converted into a string for the Roman numeral and stored inbuffer
.width()
is reset to0
).What is remaining is to create a
std::locale
using this version of thestd::num_put<char>
facet and to install the resultingstd::locale
intostd::cout
:Here is a live example showing a couple different values with different alignments. The example also implements all four integer version of
do_put()
(i.e., forlong
,long long
,unsigned long
, andunsigned long long
).