|
Boost : |
From: Rémi Chateauneu (ravioli_at_[hidden])
Date: 2002-10-22 16:03:45
/* A simple class for processing roman numbers */
#include <iostream>
#include <limits>
#include <exception>
using namespace std ;
#define ROMAN_MIN 1
#define ROMAN_MAX 4999
class roman_int_t {
typedef short integral_type ;
integral_type m_value ;
void check( integral_type the_val ) const {
if( (the_val <= ROMAN_MAX) && (the_val >= ROMAN_MIN) ) return ;
throw std::bad_cast() ;
};
public:
roman_int_t() {}
roman_int_t( integral_type the_val ) : m_value( the_val )
check( the_val );}
operator integral_type(void) const { return m_value ; };
roman_int_t & operator = (integral_type the_val ) {
check( m_value = the_val );
return *this ;
}
friend std::ostream & operator << ( std::ostream & the_o, const
roman_int_t & the_r ) {
integral_type my_rem = the_r.m_value ;
struct descr_t { int m_dec ; char m_big, m_half, m_small ; }
descr[] = {
{ 1000, '?', '?', 'M' },
{ 100, 'M', 'D', 'C' },
{ 10, 'C', 'L', 'X' },
{ 1, 'X', 'V', 'I' }
};
for( int i = 0 ; i < sizeof(descr) / sizeof(descr[0]) ; ++i ) {
const descr_t * my_d = descr + i ;
int my_digit = my_rem / my_d->m_dec ;
my_rem = my_rem - my_digit * my_d->m_dec ;
switch( my_digit ) {
case 9 : the_o << my_d->m_small << my_d->m_big ;
continue ;
case 4 : the_o << my_d->m_small << my_d->m_half ;
continue ;
case 8 :
case 7 :
case 6 :
case 5 : the_o << my_d->m_half ;
my_digit -= 5 ;
}
while( my_digit-- ) the_o << my_d->m_small ;
}
return the_o ;
};
friend std::istream & operator >> ( std::istream & the_i, roman_int_t &
the_r ) {
char myC ;
const int myDim = 4 ;
int myR[ myDim ], myI ;
for( myI = 0 ; myI < myDim; ++myI ) myR[myI] = 0 ;
for( ; ; ) {
the_i >> myC ;
if( the_i.eof() ) break ;
switch( myC ) {
case 'M' : myR[2] = -myR[2] ; myR[3]++ ; continue ;
case 'D' : myR[2] = -myR[2] ; myR[2] += 5 ; continue ;
case 'C' : myR[1] = -myR[1] ; myR[2]++ ; continue ;
case 'L' : myR[1] = -myR[1] ; myR[1] += 5 ; continue ;
case 'X' : myR[0] = -myR[0] ; myR[1]++ ; continue ;
case 'V' : myR[0] = -myR[0] ; myR[0] += 5 ; continue ;
case 'I' : myR[0]++ ; continue ;
default : break ;
};
break ;
}
int myRes = 0 ;
for( myI = myDim - 1 ; myI >= 0; --myI ) myRes = myR[myI] + 10 *
myRes ;
the_r = myRes ;
return the_i ;
};
}; // roman_int_t
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk