zoukankan      html  css  js  c++  java
  • [算法题] 人民币大小写转换(阿拉伯数字和汉字转换)

    目录

     

    在一次面试中遇到一个有意思的小算法题:要求将阿拉伯数字转为汉字显示出来(包含单位)。

    当时虽然实现出来,但是代码写的有点凌乱。所以回家后,重新整理了一下。

    这个算法有几个小的注意点:

    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 ", 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]把数字直接替换为汉字:  " << strResult << endl;

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

        ReplaceSubStr(strResult, "零亿", "亿");
        ReplaceSubStr(strResult, "零万", "万");
        if (strResult != "零圆")    //如果整数部分全为0,则不要去除元单位前面的零
        {
            ReplaceSubStr(strResult, "零圆", "圆");
        }
        
        cout << "[No.3]去除零亿、零万、零圆前面的零:  " << 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]小数精确到两位数,即精确到单位分:  " << 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;
    }
    复制代码

    结果

  • 相关阅读:
    资金流学习-成本分析
    解决root用户不能打开Chromium网页浏览器
    Kali Linux 2020.1乱码问题
    Kali Linux安装谷歌浏览器
    解决Kali Linux 2020.1乱码问题
    Kali Linux 2020.1a版本msfconsole启动失败问题
    Kali Linux发布2020.1a版本
    Kali Linux 2020.1快速修改root用户密码
    Kali Linux 2020.1安装桌面
    Kali Linux 2020.1修改系统语言
  • 原文地址:https://www.cnblogs.com/aimei/p/12199897.html
Copyright © 2011-2022 走看看