Boost logo

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