перевод числа в числительное
От: Faust Россия  
Дата: 11.12.09 07:48
Оценка: 1 (1)
#include "to_numeral.h"

std::string                aszNumeral;
int                        iNum                = -13456737;
to_numeral<int, char, ru_lower_locale_tag>(iNum, aszNumeral);
// aszNumeral = "минус тринадцать миллионов четыреста пятьдесят шесть тысяч семьсот тридцать семь "

std::wstring            wszNumeral;
__int64                    i64Num                = 13134563467;
to_numeral<__int64, wchar_t, ru_upper_locale_tag>(i64Num, wszNumeral);
// wszNumeral = "ТРИНАДЦАТЬ МИЛЛИАРДОВ СТО ТРИДЦАТЬ ЧЕТЫРЕ МИЛЛИОНА ПЯТЬСОТ ШЕСТЬДЕСЯТ ТРИ ТЫСЯЧИ ЧЕТЫРЕСТА ШЕСТЬДЕСЯТ СЕМЬ "

//////////////////////////////////////////////////////////////////////////////////////////
//
// ru_lower_locale.h
//
//////////////////////////////////////////////////////////////////////////////////////////

#ifndef __RU_LOWER_LOCALE_H__
#define __RU_LOWER_LOCALE_H__

#pragma once

//////////////////////////////////////////////////////////////////////////////////////////
struct ru_lower_locale_tag    { };
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
template <>
const char***            ToNumeralLocale<char, ru_lower_locale_tag>(void)
{
    typedef char                                                    char_type;

    static const char_type*    g_pServiceArr[]                =
    { "ноль",        "минус " };
    static const char_type*    g_pFirstNumeralArr[]        =
    { "один ",        "одиннадцать ",        "десять ",        "сто ",            "одна " };
    static const char_type*    g_pSecondNumeralArr[]        =
    { "два ",        "двенадцать ",        "двадцать ",    "двести ",        "две " };
    static const char_type*    g_pThirdNumeralArr[]            =
    { "три ",        "тринадцать ",        "тридцать ",    "триста " };
    static const char_type*    g_pFourthNumeralArr[]        =
    { "четыре ",    "четырнадцать ",    "сорок ",        "четыреста " };
    static const char_type*    g_pFifthNumeralArr[]        =
    { "пять ",        "пятнадцать ",        "пятьдесят ",    "пятьсот " };
    static const char_type*    g_pSixthNumeralArr[]        =
    { "шесть ",        "шестнадцать ",        "шестьдесят ",    "шестьсот " };
    static const char_type*    g_pSeventhNumeralArr[]        =
    { "семь ",        "семнадцать ",        "семьдесят ",    "семьсот " };
    static const char_type*    g_pEighthNumeralArr[]        =
    { "восемь ",    "восемнадцать ",    "восемьдесят ","восемьсот " };
    static const char_type*    g_pNinthNumeralArr[]        =
    { "девять ",    "девятнадцать ",    "девяносто ",    "девятьсот " };

    static const char_type*    g_pFirstTriadArr[]            =
    { "тысяча ",    "тысячи ",        "тысяч " };
    static const char_type*    g_pSecondTriadArr[]            =
    { "миллион ",    "миллиона ",    "миллионов " };
    static const char_type*    g_pThirdTriadArr[]            =
    { "миллиард ",    "миллиарда ",    "миллиардов " };
    static const char_type*    g_pFourthTriadArr[]            =
    { "триллион ",    "триллиона ",    "триллионов " };
    static const char_type*    g_pFifthTriadArr[]            =
    { "триллиард ","триллиарда ",    "триллиардов " };

    static const char_type**    g_NumeralLocale[]        =
    {
         g_pServiceArr,
         g_pFirstNumeralArr,    g_pSecondNumeralArr,    g_pThirdNumeralArr,
         g_pFourthNumeralArr,    g_pFifthNumeralArr,        g_pSixthNumeralArr,
         g_pSeventhNumeralArr,    g_pEighthNumeralArr,    g_pNinthNumeralArr,
         g_pFirstTriadArr,        g_pSecondTriadArr,        g_pThirdTriadArr,
         g_pFourthTriadArr,        g_pFifthTriadArr
    };
    return g_NumeralLocale;
}
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
template <>
const wchar_t***        ToNumeralLocale<wchar_t, ru_lower_locale_tag>(void)
{
    typedef wchar_t                                                    char_type;

    static const char_type*    g_pServiceArr[]                =
    { L"ноль",        L"минус " };
    static const char_type*    g_pFirstNumeralArr[]        =
    { L"один ",        L"одиннадцать ",    L"десять ",        L"сто ",        L"одна " };
    static const char_type*    g_pSecondNumeralArr[]        =
    { L"два ",        L"двенадцать ",        L"двадцать ",    L"двести ",        L"две " };
    static const char_type*    g_pThirdNumeralArr[]            =
    { L"три ",        L"тринадцать ",        L"тридцать ",    L"триста " };
    static const char_type*    g_pFourthNumeralArr[]        =
    { L"четыре ",    L"четырнадцать ",    L"сорок ",        L"четыреста " };
    static const char_type*    g_pFifthNumeralArr[]        =
    { L"пять ",        L"пятнадцать ",        L"пятьдесят ",    L"пятьсот " };
    static const char_type*    g_pSixthNumeralArr[]        =
    { L"шесть ",    L"шестнадцать ",    L"шестьдесят ",    L"шестьсот " };
    static const char_type*    g_pSeventhNumeralArr[]        =
    { L"семь ",        L"семнадцать ",        L"семьдесят ",    L"семьсот " };
    static const char_type*    g_pEighthNumeralArr[]        =
    { L"восемь ",    L"восемнадцать ",    L"восемьдесят ",L"восемьсот " };
    static const char_type*    g_pNinthNumeralArr[]        =
    { L"девять ",    L"девятнадцать ",    L"девяносто ",    L"девятьсот " };

    static const char_type*    g_pFirstTriadArr[]            =
    { L"тысяча ",    L"тысячи ",        L"тысяч " };
    static const char_type*    g_pSecondTriadArr[]            =
    { L"миллион ",    L"миллиона ",    L"миллионов " };
    static const char_type*    g_pThirdTriadArr[]            =
    { L"миллиард ",    L"миллиарда ",    L"миллиардов " };
    static const char_type*    g_pFourthTriadArr[]            =
    { L"триллион ",    L"триллиона ",    L"триллионов " };
    static const char_type*    g_pFifthTriadArr[]            =
    { L"триллиард ",L"триллиарда ",    L"триллиардов " };

    static const char_type**    g_NumeralLocale[]        =
    {
         g_pServiceArr,
         g_pFirstNumeralArr,    g_pSecondNumeralArr,    g_pThirdNumeralArr,
         g_pFourthNumeralArr,    g_pFifthNumeralArr,        g_pSixthNumeralArr,
         g_pSeventhNumeralArr,    g_pEighthNumeralArr,    g_pNinthNumeralArr,
         g_pFirstTriadArr,        g_pSecondTriadArr,        g_pThirdTriadArr,
         g_pFourthTriadArr,        g_pFifthTriadArr
    };
    return g_NumeralLocale;
}
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

#endif // __RU_LOWER_LOCALE_H__

//////////////////////////////////////////////////////////////////////////////////////////
//
// ru_upper_locale.h
//
//////////////////////////////////////////////////////////////////////////////////////////

#ifndef __RU_UPPER_LOCALE_H__
#define __RU_UPPER_LOCALE_H__

#pragma once

//////////////////////////////////////////////////////////////////////////////////////////
struct ru_upper_locale_tag    { };
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
template <>
const char***            ToNumeralLocale<char, ru_upper_locale_tag>(void)
{
    typedef char                                                    char_type;

    static const char_type*    g_pServiceArr[]                =
    { "НОЛЬ",        "МИНУС " };
    static const char_type*    g_pFirstNumeralArr[]        =
    { "ОДИН ",        "ОДИННАДЦАТЬ ",        "ДЕСЯТЬ ",        "СТО ",            "ОДНА " };
    static const char_type*    g_pSecondNumeralArr[]        =
    { "ДВА ",        "ДВЕНАДЦАТЬ ",        "ДВАДЦАТЬ ",    "ДВЕСТИ ",        "ДВЕ " };
    static const char_type*    g_pThirdNumeralArr[]        =
    { "ТРИ ",        "ТРИНАДЦАТЬ ",        "ТРИДЦАТЬ ",    "ТРИСТА " };
    static const char_type*    g_pFourthNumeralArr[]        =
    { "ЧЕТЫРЕ ",    "ЧЕТЫРНАДЦАТЬ ",    "СОРОК ",        "ЧЕТЫРЕСТА " };
    static const char_type*    g_pFifthNumeralArr[]        =
    { "ПЯТЬ ",        "ПЯТНАДЦАТЬ ",        "ПЯТЬДЕСЯТ ",    "ПЯТЬСОТ " };
    static const char_type*    g_pSixthNumeralArr[]        =
    { "ШЕСТЬ ",        "ШЕСТНАДЦАТЬ ",        "ШЕСТЬДЕСЯТ ",    "ШЕСТЬСОТ " };
    static const char_type*    g_pSeventhNumeralArr[]        =
    { "СЕМЬ ",        "СЕМНАДЦАТЬ ",        "СЕМЬДЕСЯТ ",    "СЕМЬСОТ " };
    static const char_type*    g_pEighthNumeralArr[]        =
    { "ВОСЕМЬ ",    "ВОСЕМНАДЦАТЬ ",    "ВОСЕМЬДЕСЯТ ","ВОСЕМЬСОТ " };
    static const char_type*    g_pNinthNumeralArr[]        =
    { "ДЕВЯТЬ ",    "ДЕВЯТНАДЦАТЬ ",    "ДЕВЯНОСТО ",    "ДЕВЯТЬСОТ " };

    static const char_type*    g_pFirstTriadArr[]            =
    { "ТЫСЯЧА ",    "ТЫСЯЧИ ",        "ТЫСЯЧ " };
    static const char_type*    g_pSecondTriadArr[]            =
    { "МИЛЛИОН ",    "МИЛЛИОНА ",    "МИЛЛИОНОВ " };
    static const char_type*    g_pThirdTriadArr[]            =
    { "МИЛЛИАРД ",    "МИЛЛИАРДА ",    "МИЛЛИАРДОВ " };
    static const char_type*    g_pFourthTriadArr[]            =
    { "ТРИЛЛИОН ",    "ТРИЛЛИОНА ",    "ТРИЛЛИОНОВ " };
    static const char_type*    g_pFifthTriadArr[]            =
    { "ТРИЛЛИАРД ","ТРИЛЛИАРДА ",    "ТРИЛЛИАРДОВ " };

    static const char_type**    g_NumeralLocale[]        =
    {
         g_pServiceArr,
         g_pFirstNumeralArr,    g_pSecondNumeralArr,    g_pThirdNumeralArr,
         g_pFourthNumeralArr,    g_pFifthNumeralArr,        g_pSixthNumeralArr,
         g_pSeventhNumeralArr,    g_pEighthNumeralArr,    g_pNinthNumeralArr,
         g_pFirstTriadArr,        g_pSecondTriadArr,        g_pThirdTriadArr,
         g_pFourthTriadArr,        g_pFifthTriadArr
    };
    return g_NumeralLocale;
}
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
template <>
const wchar_t***        ToNumeralLocale<wchar_t, ru_upper_locale_tag>(void)
{
    typedef wchar_t                                                    char_type;

    static const char_type*    g_pServiceArr[]                =
    { L"НОЛЬ",        L"МИНУС " };
    static const char_type*    g_pFirstNumeralArr[]        =
    { L"ОДИН ",        L"ОДИННАДЦАТЬ ",    L"ДЕСЯТЬ ",        L"СТО ",        L"ОДНА " };
    static const char_type*    g_pSecondNumeralArr[]        =
    { L"ДВА ",        L"ДВЕНАДЦАТЬ ",        L"ДВАДЦАТЬ ",    L"ДВЕСТИ ",        L"ДВЕ " };
    static const char_type*    g_pThirdNumeralArr[]        =
    { L"ТРИ ",        L"ТРИНАДЦАТЬ ",        L"ТРИДЦАТЬ ",    L"ТРИСТА " };
    static const char_type*    g_pFourthNumeralArr[]        =
    { L"ЧЕТЫРЕ ",    L"ЧЕТЫРНАДЦАТЬ ",    L"СОРОК ",        L"ЧЕТЫРЕСТА " };
    static const char_type*    g_pFifthNumeralArr[]        =
    { L"ПЯТЬ ",        L"ПЯТНАДЦАТЬ ",        L"ПЯТЬДЕСЯТ ",    L"ПЯТЬСОТ " };
    static const char_type*    g_pSixthNumeralArr[]        =
    { L"ШЕСТЬ ",    L"ШЕСТНАДЦАТЬ ",    L"ШЕСТЬДЕСЯТ ",    L"ШЕСТЬСОТ " };
    static const char_type*    g_pSeventhNumeralArr[]        =
    { L"СЕМЬ ",        L"СЕМНАДЦАТЬ ",        L"СЕМЬДЕСЯТ ",    L"СЕМЬСОТ " };
    static const char_type*    g_pEighthNumeralArr[]        =
    { L"ВОСЕМЬ ",    L"ВОСЕМНАДЦАТЬ ",    L"ВОСЕМЬДЕСЯТ ",L"ВОСЕМЬСОТ " };
    static const char_type*    g_pNinthNumeralArr[]        =
    { L"ДЕВЯТЬ ",    L"ДЕВЯТНАДЦАТЬ ",    L"ДЕВЯНОСТО ",    L"ДЕВЯТЬСОТ " };

    static const char_type*    g_pFirstTriadArr[]            =
    { L"ТЫСЯЧА ",    L"ТЫСЯЧИ ",        L"ТЫСЯЧ " };
    static const char_type*    g_pSecondTriadArr[]            =
    { L"МИЛЛИОН ",    L"МИЛЛИОНА ",    L"МИЛЛИОНОВ " };
    static const char_type*    g_pThirdTriadArr[]            =
    { L"МИЛЛИАРД ",    L"МИЛЛИАРДА ",    L"МИЛЛИАРДОВ " };
    static const char_type*    g_pFourthTriadArr[]            =
    { L"ТРИЛЛИОН ",    L"ТРИЛЛИОНА ",    L"ТРИЛЛИОНОВ " };
    static const char_type*    g_pFifthTriadArr[]            =
    { L"ТРИЛЛИАРД ",L"ТРИЛЛИАРДА ",    L"ТРИЛЛИАРДОВ " };

    static const char_type**    g_NumeralLocale[]        =
    {
         g_pServiceArr,
         g_pFirstNumeralArr,    g_pSecondNumeralArr,    g_pThirdNumeralArr,
         g_pFourthNumeralArr,    g_pFifthNumeralArr,        g_pSixthNumeralArr,
         g_pSeventhNumeralArr,    g_pEighthNumeralArr,    g_pNinthNumeralArr,
         g_pFirstTriadArr,        g_pSecondTriadArr,        g_pThirdTriadArr,
         g_pFourthTriadArr,        g_pFifthTriadArr
    };
    return g_NumeralLocale;
}
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

#endif // __RU_UPPER_LOCALE_H__

//////////////////////////////////////////////////////////////////////////////////////////
//
// to_numeral_locale.h
//
//////////////////////////////////////////////////////////////////////////////////////////

#ifndef __TO_NUMERAL_LOCALE_H__
#define __TO_NUMERAL_LOCALE_H__

#pragma once

//////////////////////////////////////////////////////////////////////////////////////////
template <typename CharType, typename LocaleTag>
const CharType***        ToNumeralLocale(void);

#include "ru_lower_locale.h"
#include "ru_upper_locale.h"
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
template <typename CharType, typename LocaleTag>
struct to_numeral_locale
{
    typedef CharType                                                char_type;
    typedef LocaleTag                                                locale_tag;

    //////////////////////////////////////////////////////////////////////////////////////
    static const char_type*    Null(void)
    { return ToNumeralLocale<char_type, locale_tag>()[0][0]; }
    static const char_type*    Minus(void)
    { return ToNumeralLocale<char_type, locale_tag>()[0][1]; }

    static const char_type*    Numeral(const int ciDigit, const int ciExt)
    { return ToNumeralLocale<char_type, locale_tag>()[ciDigit][ciExt]; }

    static const char_type*    TriadName(const int ciIndex, const int ciExt)
    { return ToNumeralLocale<char_type, locale_tag>()[9 + ciIndex][ciExt]; }
    //////////////////////////////////////////////////////////////////////////////////////
};
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

#endif // __TO_NUMERAL_LOCALE_H__

//////////////////////////////////////////////////////////////////////////////////////////
//
// to_numeral.h
//
//////////////////////////////////////////////////////////////////////////////////////////

#ifndef __TO_NUMERAL_H__
#define __TO_NUMERAL_H__

#pragma once

#include <string>
#include <vector>
#include "to_numeral_locale.h"

//////////////////////////////////////////////////////////////////////////////////////////
template <typename NumType, typename CharType, typename LocaleTag>
class to_numeral
{
public:
    typedef NumType                                                    num_type;
    typedef CharType                                                char_type;
    typedef LocaleTag                                                locale_tag;
    typedef to_numeral_locale<char_type, locale_tag>                locale_type;
    typedef std::basic_string<char_type>                            string;

    //////////////////////////////////////////////////////////////////////////////////////
public:
                            to_numeral(const num_type tNum, string& szOut)
    { Proccess(tNum, szOut); }
private:
                            to_numeral(void);
                            to_numeral(const to_numeral&);
    //////////////////////////////////////////////////////////////////////////////////////

private:
    //////////////////////////////////////////////////////////////////////////////////////
    inline void                Proccess(const num_type tOrigNum, string& szOut) const
    {
        if(!tOrigNum)            { szOut = locale_type::Null(); return; }
        else                    szOut.clear();

        std::vector<int>        vDigit;
        {
        num_type                tNum                    =
            (tOrigNum > 0 ? tOrigNum : (szOut = locale_type::Minus(), -tOrigNum));
        do { vDigit.push_back(tNum % 10); tNum /= 10; } while(tNum);
        }

        typedef std::vector<int>::const_iterator                        const_it;
        const_it                citCursor                = vDigit.end();
        // порядок чиса
        const int                iExp                    = vDigit.size();
        // количество триад
        int                        iTriad                    = (iExp / 3) - (!(iExp % 3) ? 1 : 0);
        // количество цифр в старшей триаде
        int                        iCount                    = (iExp - (iTriad * 3));
        int                        iDigit                    = 0;
        int                        iTriadName                = -1;

        do
        {
            do
            {
                if(!(iDigit = *(--citCursor)))    continue;
                switch(iCount)
                {
                //////////////////////////////////////////////////////////////////////////
                case 1:                        // единицы
                    if(iTriad == 1 && iDigit < 3)
                        szOut += locale_type::Numeral(iDigit, 4);
                    else
                        szOut += locale_type::Numeral(iDigit, 0);
                    switch(iDigit)
                    {
                        case 1:        iTriadName = 0;    break;
                        case 2:
                        case 3:
                        case 4:        iTriadName = 1;    break;
                        default:    iTriadName = 2;    break;
                    }
                    break;
                //////////////////////////////////////////////////////////////////////////
                case 2:                        // десятки
                    if(iDigit == 1)            // вторая десятка
                    {
                        iDigit = *(--citCursor);
                        if(!iDigit)        szOut += locale_type::Numeral(1, 2);
                        else            szOut += locale_type::Numeral(iDigit, 1);
                        --iCount;
                    }
                    else
                        szOut += locale_type::Numeral(iDigit, 2);
                    iTriadName = 2;
                    break;
                //////////////////////////////////////////////////////////////////////////
                case 3:                        // сотни
                    szOut += locale_type::Numeral(iDigit, 3);
                    iTriadName = 2;
                    break;
                //////////////////////////////////////////////////////////////////////////
                }
            }
            while(--iCount);
            if(!iTriad)                return;
            if(iTriadName != -1)    szOut += locale_type::TriadName(iTriad, iTriadName);
            iTriadName                = -1;
            iCount                    = 3;
            --iTriad;
        }
        while(true);
    }
    //////////////////////////////////////////////////////////////////////////////////////
};
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

#endif // __TO_NUMERAL_H__
Мой компьютер прогоняет бесконечный цикл за 9 секунд, но, мне кажется, он мог бы сделать это быстрее...
числительное
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.