需求:写一个程序,实现货币的小写转换成大写形式(符合习惯)
例如:输入123,456,789.02返回相应的大写 壹亿贰仟叁佰肆拾伍万陆仟柒佰捌拾玖元零贰分;
输入1000,返回壹仟元整;
#include "stdafx.h"
#include "math.h"
#include <string>
#include <iostream>
using namespace std;
#define INTEGER_ONLY 1 // 表示整数部分的标志
#define DECIMAL_ONLY 2 // 表示小数部分的标志
/*
需求:写一个程序,实现货币的小写转换成大写形式(符合习惯)
例如:输入123,456,789.02返回相应的大写 壹亿贰仟叁佰肆拾伍万陆仟柒佰捌拾玖元零贰分;
输入1000,返回壹仟元整;
*/
/*
string类的成员函数说明:
1)
原型:double atof(const char *nptr);
功 能: 把字符串转换成浮点数
名字来源:ascii to floating point numbers 的缩写
2)
原型:char *fcvt(double value, int ndigit, int *decpt, int *sign);
功能: 把一个浮点数转换为字符串
参数:
value:要转换的浮点数, 输入参数
ndigit:小数点后面的位数, 输入参数
decpt:表示小数点的位置, 输出参数
sign:表示符号,0为正数,1为负数,输出参数
3)
原型:string replace(string src, length, replacement);
功能:替换 src 字符串中从第一个匹配src的字符串索引开始的 length 个字符为 replacement 字符串
输出:替换后的string类型
*/
/*
*********************************************************************
功能:获得用户输入的string
输入:无
输出:string类型
*********************************************************************
*/
string getNum() {
string s;
cout << "请输入一个数字(精确到小数点后两位):"<< endl;
cin >> s;
return s;
}
/*
*********************************************************************
功能:将输入的数字字符串转换为double类型,并检查输入的有效性(为正数)
输入:string类型
输出:bool类型:true,正数; false,负数
*********************************************************************
*/
bool checkNum(string& str)
{
// 检查输入非数字的字符
bool flag = true;
double d = atof(str.c_str()); //把字符串转换成浮点数
if(d < 0)
flag = false;
return flag;
}
/*
*********************************************************************
功能:将这个数转换成 double 类型,并对其进行四舍五入操作
输入:string类型
输出:string类型
*********************************************************************
*/
string roundString(string s)
{
double d = atof(s.c_str()); /* 转换成 double 类型 */
int dec, sign; /* fcvt()函数输出参数 */
s = fcvt(d, 2, &dec, &sign); /* 将这个数进行四舍五入,保留到小数点后两位;
当这个数转换成字符串以后不会显示小数点,
并且会以四舍五入的形式只保留小数点后两位 */
if(s.length() > 15) /* 规定数值的最大长度只能是15位(到万亿位) */
{
cout << "提示:输入数据过大!(整数部分最多13位!)"<< endl;
return "";
}
return s;
}
/*
*********************************************************************
功能:将这个数转换成 double 类型,并对其进行四舍五入操作
输入:标志位flag,string类型
输出:string类型
*********************************************************************
*/
string formatChinese(int flag, string s) {
int sLength = s.length();
string bigLetter[] = {"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"}; /* 货币大写形式 */
string small[] = {"分", "角"}; /*分位到角位 */
string unit[] = {"元", "拾", "佰", "仟", /*个位到仟位 */
"万", "拾", "佰", "仟", /*拾万位到仟万位 */
"亿", "拾", "佰", "仟", "万"}; /*亿位到万亿位 */
string newS = ""; /* 用来存放转换后的新字符串 */
for(int i = 0; i < sLength; i ++) /* 逐位替换为中文大写形式 */
{
if(flag == INTEGER_ONLY) /* 转换整数部分为中文大写形式(带单位) */
{
newS = newS + bigLetter[s.at(i) - '0'] + unit[sLength-1 - i];
}
else if(flag == DECIMAL_ONLY) /* 转换小数部分(带单位) */
{
newS = newS + bigLetter[s.at(i) - '0'] + small[sLength-1 - i];
}
}
return newS;
}
/*
*********************************************************************
功能:将这个数分割成整数部分和小数部分,转换成对应的货币的中文大写形式
输入:string类型
输出:string类型
*********************************************************************
*/
string splitNum(string s)
{
if("" == s) /* 如果传入的是空串则继续返回空串 */
{
return "";
}
string IntegerOnly = s.substr(0, s.size() - 2); /* 截取输入数字的整数部分 */
string IntegerPart = formatChinese(INTEGER_ONLY, IntegerOnly);
string DecimalOnly = s.substr(s.size() - 2, s.size()); /* 截取这个数的小数部分 */
string DecimalPart = formatChinese(DECIMAL_ONLY, DecimalOnly);
string newS = IntegerPart + DecimalPart; /* 把转换好了的整数部分和小数部...
...分重新拼凑一个新的字符串 */
return newS;
}
/*
*********************************************************************
功能:将非规范性货币中文大写表达形式转换成规范的货币中文大写形式
输入:string类型(source),string类型(搜索字符串),string类型(替代字符串)
输出:string类型
*********************************************************************
*/
string replaceAll(string src, string regex, string replacement) {
int length = regex.length();
while(src.find(regex) < src.length())
{
src.replace(src.find(regex), length, replacement);
}
return src;
}
/*
*********************************************************************
功能:将非规范性货币中文大写表达形式转换成规范的货币中文大写形式
输入:string类型
输出:string类型
*********************************************************************
*/
string cleanZero(string s)
{
if("" == s) /* 如果传入的是空串则返回空串 */
{
return "";
}
string regex1[] = {"零仟", "零佰", "零拾"};
string regex2[] = {"零亿", "零万", "零元"};
string regex3[] = {"亿", "万", "元"};
string regex4[] = {"零角", "零分"};
// 字符串中存在多个'零'在一起的时候只读出一个'零',并省略多余的单位
for(int i = 0; i < 3; i ++){ /* case1: 把 "零仟", 零佰","零拾"...
...等字符串替换成一个"零" */
s = replaceAll(s, regex1[i], "零");
}
s = replaceAll(s, "零零零", "零");
s = replaceAll(s, "零零", "零"); /* 当第一轮转换过后有可能有很多个零叠在一起,
...要把很多个重复的零变成一个零 */
for(int i = 0; i < 3; i ++) /* 第二轮转换考虑 "零亿","零万","零元"等情况 */
{
s = replaceAll(s, regex2[i], regex3[i]); /* "亿","万","元"这些单位有些情况是...
...不能省的,需要保留下来 */
}
s = replaceAll(s,"零角零分","整"); /* 考虑没有小数的情况 */
for(int i = 0; i < 2; i ++) { /* 第三轮转换把"零角","零分"字符串省略 */
s = replaceAll(s, regex4[i], "");
}
s = replaceAll(s, "亿万", "亿"); /* 当"万"到"亿"之间全部是"零"的时候,
...忽略"亿万"单位,只保留一个"亿" */
return s;
}
int _tmain(int argc, _TCHAR* argv[])
{
cout << "\n------------将数字转换成中文金额的大写形式(C++)------------\n" << endl;
for(;;)
{
string s = getNum();
if(checkNum(s)) /* 检查用户输入是否有效 */
{
s = roundString(s); /* 用四舍五入规范浮点数,保留两位 */
s = splitNum(s); /* 把浮点数分割成小数和整数部分,分别表示为...
...货币的大写形式 */
s = cleanZero(s); /* 把货币的大写形式规范化 */
cout << "转换成中文后为:" << s << endl;
}
else
{
cout << "非法输入,程序即将退出" << endl;
}
cout << "\n--------------------------------------------------------------" << endl;
}
return 0;
}
输出结果: