当时虽然实现出来,但是代码写的有点凌乱。所以回家后,重新整理了一下。
这个算法有几个小的注意点:
1、中文字符占两个字节,所以如果用C语言实现,需要用char数组的形式保存单个汉字。
2、如果数字中出现连续的零,需要把它替换为单一的零。
3、在亿、万、元的前面一个汉字不可以为零(人民币读取方式决定)。
4、double数值可分为整数部分和小数部分。小数部分较简单,整数部分需要根据这个数字所在的位数匹配上对应的单位。
具体方法是:设置一个单位映射字符串表g_strUnit,可视为一个简单的HashTable。然后从头开始读取整数字符串的每个
字符,若这个字符在整数字符串的位置为i,这个字符后面的单位就是g_strUnit[length-1-i]。
代码如下
/* ******************************************************************************Project Code : AccountFile name : Author : LatteDescription : 阿拉伯数字转为中文字符串Function List :--------------------------------------------------------------------------------History:Date Author Modification20140703 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 : ReplaceSubStrDate Created : 2014-07-03Author : LatteDescription : 将源字符串strOrig中第一个匹配strSub的子串部分替换为strReplaceInput : string &strOrig, string strSub, string strReplaceOutput : string &strOrigReturn : intCaution : 返回值如果为-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 : NumToChineseStrDate Created : 2014-07-03Author : LatteDescription : 将人民币double数值转化为人民币汉字stringInput : double moneyOutput : Return : stringCaution :****************************************************************************** */ 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; }
结果