[算法題] 人民幣大小寫轉換(阿拉伯數字和漢字轉換)


在一次面試中遇到一個有意思的小算法題:要求將阿拉伯數字轉為漢字顯示出來(包含單位)。

當時雖然實現出來,但是代碼寫的有點凌亂。所以回家后,重新整理了一下。

 

這個算法有幾個小的注意點:

1、中文字符占兩個字節,所以如果用C語言實現,需要用char數組的形式保存單個漢字。

2、如果數字中出現連續的零,需要把它替換為單一的零。

3、在億、萬、元的前面一個漢字不可以為零(人民幣讀取方式決定)。

4、double數值可分為整數部分和小數部分。小數部分較簡單,整數部分需要根據這個數字所在的位數匹配上對應的單位。

具體方法是:設置一個單位映射字符串表g_strUnit,可視為一個簡單的HashTable。然后從頭開始讀取整數字符串的每個

字符,若這個字符在整數字符串的位置為i,這個字符后面的單位就是g_strUnit[length-1-i]。

 

代碼如下

/* ******************************************************************************
Project Code  : Account
File name     : 
Author        : Latte
Description   : 阿拉伯數字轉為中文字符串
Function List :
--------------------------------------------------------------------------------
History:
Date            Author          Modification
20140703        Latte           created file.
******************************************************************************
*/

#include  " stdafx.h "
#include < string>
#include <iostream>
using  namespace std;

#define MAX 100
string g_strDigit[] = { " "" "" "" "" "" "" "" "" "" "};

string g_strUnit[] = { " "" "" "" "" "" "" "" "" "
                       " "" "" "" "" "" "};

string g_strUnit2[] = { " "" "};

/* ******************************************************************************
Func Name       : ReplaceSubStr
Date Created    : 2014-07-03
Author          : Latte
Description     : 將源字符串strOrig中第一個匹配strSub的子串部分替換為strReplace
Input           : 
                  string &strOrig, 
                  string strSub, 
                  string strReplace
Output          : 
                  string &strOrig
Return          : 
                  int
Caution         : 返回值如果為-1,則表示替換失敗或未找到替換項
******************************************************************************
*/
int ReplaceSubStr( string &strOrig,  string strSub,  string strReplace)
{
     int pos = ( int)strOrig.find(strSub);
     int length = ( int)strSub.length();
    
     if (pos >=  0)
    {
        strOrig.replace(pos, length, strReplace);
         return  0;
    }
    
     return - 1;
}

/* ******************************************************************************
Func Name       : NumToChineseStr
Date Created    : 2014-07-03
Author          : Latte
Description     : 
                  將人民幣double數值轉化為人民幣漢字string
Input           : 
                  double money
Output          : 
Return          : 
                  string
Caution         :
******************************************************************************
*/
string NumToChineseStr( double money)
{
     int i               =  0;
     int ret             =  0;
     int length          =  0;
     char *p             = NULL;
     char *pcDecimal     = NULL;  // 保存小數部分字符
     char czNumber[MAX]  = { 0};   // 保存完整數字部分字符
     string strResult;

    cout <<  " ====================================== " << endl;
    cout << money << endl;

     // 判斷是否為小數
     if (money <  0)
    {
        strResult =  " 不支持讀負數 ";   
         return strResult;   
    }

     // 將數字轉為數字字符串,利用sprintf_s的正則轉換
    sprintf_s(czNumber, MAX,  " %.15lg ", money);
    printf( " [No.0]%s\n ", czNumber); 

     // 如果數字是太大或太小的數,因為已經轉為科學計數,所以會含有e字符
    p = strchr(czNumber, ' e ');  
     if (NULL!=p) 
    {
        strResult =  " 不支持讀太大或太小的數 ";
         return strResult;
    }
    
    p = strchr(czNumber,  ' . ');  
     if (NULL != p) 
    {       
        p[ 0] =  0;    
        pcDecimal = p +  1;   
    }    
    length = ( int)strlen(czNumber);  
    
     for (i =  0; i<length; i++) 
    {        
         if ( ' 0 ' == czNumber[i] &&  0 != ((length- 1-i) %  4))
        {
            strResult += g_strDigit[czNumber[i] -  ' 0 '];
        } 
         else 
        {
            strResult += g_strDigit[czNumber[i] -  ' 0 '] + g_strUnit[length- 1-i];
        }   
    }
    cout <<  " [No.1]把數字直接替換為漢字: \n " << strResult << endl;

     // 把strResult中的所有"零零"子串替換為"零"
     while ( 1)
    {
        ret = ReplaceSubStr(strResult,  " 零零 "" ");
         if (ret <  0)
        {
             break;
        }
    }
    cout <<  " [No.2]替換所有零零為零: \n " << strResult << endl;

    ReplaceSubStr(strResult,  " 零億 "" ");
    ReplaceSubStr(strResult,  " 零萬 "" ");
     if (strResult !=  " 零圓 ")     // 如果整數部分全為0,則不要去除元單位前面的零
    {
        ReplaceSubStr(strResult,  " 零圓 "" ");
    }
    
    cout <<  " [No.3]去除零億、零萬、零圓前面的零: \n " << strResult << endl;

     // 小數精確到兩位數,即精確到單位分
     if (NULL != pcDecimal) 
    {
         // 如果小數部分有數值而整數部分為0,則刪除字符串中的零元
         if (strResult ==  " 零圓 ")
        {
            strResult.clear();
        }
        i =  0;
         while ( 1
        {           
             if ( 0 == pcDecimal[i] || i >=  2
                 break;   
            strResult += g_strDigit[pcDecimal[i] -  ' 0 '] + g_strUnit2[i];
            i++;      
        }   
    }
    cout <<  " [No.4]小數精確到兩位數,即精確到單位分: \n " << strResult << endl;
    
     return strResult;
}

int main( void)
{
     // cout << "Result: " << NumToChineseStr(0.00) << endl;
    
// cout << "Result: " << NumToChineseStr(-345.67) << endl;
    
// cout << "Result: " << NumToChineseStr(1000.0) << endl;
    cout <<  " Result:  " << NumToChineseStr( 130040600090.012) << endl;

     return  0;
}

 

結果


免責聲明!

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



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