C++ - 阿拉伯數字轉化為中文表示


1、代碼摘自 《算法的樂趣》

// chinese_num.cpp : Defines the entry point for the console application.
//
#include <string>
#include <cassert>

//using namespace std;

const int CHN_NUM_CHAR_COUNT = 10;
const int CHN_CHAR_LENGTH = 2;

const char *chnNumChar[CHN_NUM_CHAR_COUNT] = { "", "", "", "", "", "", "", "", "", "" };
const char *chnUnitChar[] = { "", "", "", "" };
const char *chnUnitSection[] = { "", "", "", "萬億" };

typedef struct 
{
    const char *name; //中文權位名稱
    int value; //10的倍數值
    bool secUnit; //是否是節權位
}CHN_NAME_VALUE;

CHN_NAME_VALUE chnValuePair[] = 
{
    { "", 10, false }, { "", 100, false }, { "", 1000, false }, 
    { "", 10000, true }, { "", 100000000, true }
};



void SectionToChinese(unsigned int section, std::string& chnStr)
{
    chnStr.clear();
    std::string strIns;
    int unitPos = 0;
    bool zero = true;
    while(section > 0)
    {
        int v = section % 10;
        if(v == 0)
        {
            if( (section == 0) || !zero )
            {
                zero = true; /*需要補0,zero的作用是確保對連續的多個0,只補一個中文零*/
                chnStr.insert(0, chnNumChar[v]);
            }
        }
        else
        {
            zero = false; //至少有一個數字不是0
            strIns = chnNumChar[v]; //此位對應的中文數字
            strIns += chnUnitChar[unitPos]; //此位對應的中文權位
            chnStr.insert(0, strIns); 
        }
        unitPos++; //移位
        section = section / 10;
    }
}

//num == 0需要特殊處理,直接返回"零"
void NumberToChinese(unsigned int num, std::string& chnStr)
{
    chnStr.clear();
    int unitPos = 0;
    std::string strIns;
    bool needZero = false;

    if(num == 0)
    {
        chnStr = chnNumChar[0];
        return;
    }

    while(num > 0)
    {
        unsigned int section = num % 10000;
        if(needZero)
        {
            chnStr.insert(0, chnNumChar[0]);
        }
        SectionToChinese(section, strIns);
        /*是否需要節權位?*/
        strIns += (section != 0) ? chnUnitSection[unitPos] : chnUnitSection[0]; 
        chnStr.insert(0, strIns);
        /*千位是0?需要在下一個section補零*/
        needZero = (section < 1000) && (section > 0); 
        num = num / 10000;
        unitPos++;
    }
}

int ChineseToValue(const std::string& chnStr)
{
    for(int val = 0; val < sizeof(chnNumChar) / sizeof(chnNumChar[0]); val++)
    {
        if(chnStr.compare(chnNumChar[val]) == 0)
        {
            return val;
        }
    }

    return -1;
}

int ChineseToUnit(const std::string& chnStr, bool& secUnit)
{
    for(int unit = 0; unit < sizeof(chnValuePair) / sizeof(chnValuePair[0]); unit++)
    {
        if(chnStr.compare(chnValuePair[unit].name) == 0)
        {
            secUnit = chnValuePair[unit].secUnit;
            return chnValuePair[unit].value;
        }
    }

    return 1;
}

unsigned int ChineseToNumber(const std::string& chnString)
{
    unsigned int rtn = 0;
    unsigned int section = 0;
    int number = 0;
    bool secUnit = false;
    std::string::size_type pos = 0;
    
    while(pos < chnString.length())
    {
        int num = ChineseToValue(chnString.substr(pos, CHN_CHAR_LENGTH));
        if(num >= 0) /*數字還是單位?*/
        {
            number = num;
            pos += CHN_CHAR_LENGTH;
            if(pos >= chnString.length())//如果是最后一位數字,直接結束
            {
                section += number;
                rtn += section;
                break;
            }
        }
        else
        {
            int unit = ChineseToUnit(chnString.substr(pos, CHN_CHAR_LENGTH), secUnit);
            if(secUnit)//是節權位說明一個節已經結束
            {
                section = (section + number) * unit;
                rtn += section;
                section = 0;
            }
            else
            {
                section += (number * unit);
            }
            number = 0;
            pos += CHN_CHAR_LENGTH;
            if(pos >= chnString.length())
            {
                rtn += section;
                break;
            }
        }
    }

    return rtn;
}

typedef struct 
{
    int num;
    const char *chnNumStr;
}TEST_DATA;

TEST_DATA testPair[] = 
{
    {0, ""},
    {1, ""},
    {2, ""},
    {3, ""},
    {4, ""},
    {5, ""},
    {6, ""},
    {7, ""},
    {8, ""},
    {9, ""},
    {10, "一十"},
    {11, "一十一"},
    {110, "一百一十"},
    {111, "一百一十一"},
    {100, "一百"},
    {102, "一百零二"},
    {1020, "一千零二十"},
    {1001, "一千零一"},
    {1015, "一千零一十五"},
    {1000, "一千"},
    {10000, "一萬"},
    {20010, "二萬零一十"},
    {20001, "二萬零一"},
    {100000, "一十萬"},
    {1000000, "一百萬"},
    {10000000, "一千萬"},
    {100000000, "一億"},
    {1000000000, "一十億"},
    {1000001000, "一十億一千"},
    {1000000100, "一十億零一百"},
    {200010, "二十萬零一十"},
    {2000105, "二百萬零一百零五"},
    {20001007, "二千萬一千零七"},
    {2000100190, "二十億零一十萬零一百九十"},
    {1040010000, "一十億四千零一萬"},
    {200012301, "二億零一萬二千三百零一"},
    {2005010010, "二十億零五百零一萬零一十"},
    {4009060200, "四十億零九百零六萬零二百"},
    {4294967295, "四十二億九千四百九十六萬七千二百九十五"}
};

void testNumberToChinese()
{
    std::string chnNum;

    for(int i = 0; i < sizeof(testPair)/sizeof(testPair[0]); i++)
    {
        NumberToChinese(testPair[i].num, chnNum);
        assert(strcmp(chnNum.c_str(), testPair[i].chnNumStr) == 0);
    }
}

void testChineseToNumber()
{
    for(int i = 0; i < sizeof(testPair)/sizeof(testPair[0]); i++)
    {
        unsigned int num = ChineseToNumber(testPair[i].chnNumStr);
        assert(num == testPair[i].num);
    }
}

int main(int argc, char* argv[])
{
    testNumberToChinese();
    testChineseToNumber();
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM