金额大写转换(C语言 )
本人喜欢探索各种算法。见站内好多此类文章,有些很好,有些不完整。姑且也来凑下热闹。
金额大写应用在很多方面,如支票、发票、各种单据,各种财务凭证,合同文本金额部分。财务方面制定了一套标准的表达法。财务上金额大写是没有负数的,财务上分借方和贷方,负数就是借方红字和贷方红字,也就是赤字。大写转换的算法要按财务管理的标准来设置。本文详细介绍算法的要点。
算法的要点:
简单地讲就是字串转换处理。若输入是数值型则转为字串型。
将输入的金额分成整数部分和小数部分,按金额数值逐位转换成中文,拼成大写字串,然后输出。
对于不含零的情况,直接就转换好了。然而对于含零和连续多个零的情况就要消除多余的零。本文介绍的算法就是 ”截数值位消零法”,或称 ”截位消零法” 。
要处理的是整数部分,分三步:
一是 先换成2个字符的数字和单位中文表达,
二是 按2个字符截取字段, 将含零的字段消去单位,
三是 处理多余的零。
转换的算法就一个函数:
Function exchange ( ) { //传入 snum 输出金额大写
M$="零元拾佰仟万拾佰仟亿拾佰仟万拾佰仟" ;
//对输入字串截取整数部分 fn$ 和小数部分 sn$
nlen=len(snum) ;
n=nlen ;
for (i=0; i<nlen ; i++){
g$= subString (snum, i,1 ) ;
if(g$==".") n= i ; }
if (nlen-n>2) sn$=subString (snum,n+1,2) ;
if (nlen-n==2) sn$=subString (snum,n+1,1)+"0" ;
if (nlen-n==0) sn$="00" ; //无小数
fn$=subString (snum,0,n) ; //截取整数部分
print "输入金额 snum = ", snum ;
// print "整数部分 fn = ", fn$ ; //test
// print "小数角分 sn = ", sn$ ;
//开始转换,先处理整数 fn$ ******
nlen=len (fn$) ; //字串长度
chb$=" " ; chs$=" " ;
for (i=0; i<nlen ; i++){
a$= subString (fn$, i,1 ) ;
snToD () ; //数字转大写 得c$
b$=subString (M$,nlen-i,1) ;
chb$=chb$+c$+b$ ; //整数已转换
}
if (sn$=="00") { //小数部分角分为零
chb$=chb$+"整" ;
goto result ; } //无小数转输出
//角分小数部分 ******
d1$=subString(sn$,0,1) ;
d2$=subString(sn$,1,1) ;
// print d1$ +" "+d2$ ; //test
if (d1$=="0" ){
c$="零" ; }else{
a$=d1$ ;
snToD ();
c$=c$+"角" ; }
d$ =c$ ;
if (d2$=="0" ){
c$="整" ; }else{
a$=d2$ ;
snToD ();
c$=c$+"分" ; }
d$ =d$+c$ ;
chs$=d$ ; //小数chs$已转换
//输出结果 ******
//上述计算已得到整数和小数部分的字串chb$ , chs$
//对于含零的位数需进一步处理。下面的算法可称为
// ”截数值位消零法”,或称 ”截位消零法” 。
result :
string pn$[20] ;
p$=" " ;
nlen=len (chb$)/2 ; //按中文二字组字串
for (i=0; i<20 ; i++){ pn$[i]=" " ; }
for (i=0; i<nlen ; i++){
pn$[i]=subString(chb$, i*2+1, 2) ; }
for (i=0; i<nlen ; i++){
p$=p$+pn$[i]+" " ; }
// print p$ ; //测试
//按位数处理” 零” format **********
for (i=0; i<nlen ; i++){
p$=pn$[i] ;
if (p$=="零仟") { pn$[i]="零" ; }
if (p$=="零佰") { pn$[i]="零" ; }
if (p$=="零拾") { pn$[i]="零" ; }
if (p$=="零元") { pn$[i]="元" ; }
if (p$=="零万") { pn$[i]="万" ; }
if (p$=="零亿") { pn$[i]="亿" ; }
} //format
//处理连续位数零的整数部分 ******
chb$=" " ;
for (i=0; i<nlen ; i++){ //重组整数部分>去零
chb$=chb$+pn$[i] ; }
// print chb$+chs$ ; //测试
p$=" " ;
nlen=len (chb$) ;
for (i=0; i<20 ; i++){ pn$[i]=" " ; }
for (i=0; i<nlen ; i++){
pn$[i]=subString(chb$, i, 1) ; }
for (i=0; i<nlen ; i++){ //去多余 ”零”
p$=pn$[i] ;
if (p$=="零"&&pn$[i+1]=="零" ) { pn$[i]="" ; }
if (p$=="零"&&pn$[i+1]=="元" ) { pn$[i]="" ; }
if (p$=="零"&&pn$[i+1]=="万" ) { pn$[i]="" ; }
if (p$=="零"&&pn$[i+1]=="亿" ) { pn$[i]="" ; }
}
chb$=" " ;
for (i=0; i<nlen ; i++){ //去零后重组整数部分
chb$=chb$+pn$[i] ; }
//特殊情况100000902 大写: 壹亿万零玖佰零贰元整
//测试时碰到此例 ”壹亿万零... ” 要消 "万" ****
//string p1$, p2$ ;
nlen= len (chb$) ;
for (i=0; i<nlen ; i++){ //特殊情况
a$=subString (chb$, i, 1 ) ;
b$=subString (chb$, i+1, 1 ) ;
if (a$=="亿"&&b$=="万") {
a$=subString (chb$, 1, i) ;
b$=subString (chb$, i+2, nlen-i ) ;
chb$= a$+b$ ; } }
//输出结果 ******
// print " " ;
print " 大写输出:" ;
print chb$+chs$ ;
print "……………………………………...>" ;
}//exchange ()
//以下是示例源码:
// **** 财务金额大写显示 **************
// 本代码是用简单的 C 语言写的,用 MySpringC
// v2.7 编译调试通过。可以 VB6, C++, Java 改写。
// 编译人:张纯叔(micelu@126.com )
//*******************************************
string sBarDes[10];
int nBarId[10];
string snum ; //输入金额
int n, i, j ;
string N$ , M$ ; //预设置大写字符
string a$, c$; //转换 传入a$ 输出c$
string d$, d1$, d2$ ; //计算小数角分
string fn$, sn$ ; //整数字串,小数字串
string chs$, chb$ ; //小写,大写
int nlen ; //字数
string b$, g$, p$ ; //计算
main(){
setDisplay (0);
sBarDes[0]="输入金额";
nBarId[0]=100;
sBarDes[1]=" 测 试 ";
nBarId[1]=101;
sBarDes[2]=" 示 例 ";
nBarId[2]=102;
sBarDes[3]=" ";
nBarId[3]=103;
sBarDes[4]="退出程序 ";
nBarId[4]=104;
setToolBarHeight(10);
setButtonTextSize(15);
setToolBarBackgroundColor(255,220,220,220);
setButtonColor(255,240,240,240);
setButtonTextColor(255,0,0,200);
setToolBar(100,myToolBarProc,sBarDes,nBarId,6);
setTitle("金额大写显示");
while (){}
}//main ()
exchange (){ //开始转换
M$="零元拾佰仟万拾佰仟亿拾佰仟万拾佰仟" ;
//对输入字串截取整数部分和小数部分
nlen=len(snum) ;
n=nlen ;
for (i=0; i<nlen ; i++){
g$= subString (snum, i,1 ) ;
if(g$==".") n= i ; }
if (nlen-n>2) sn$=subString (snum,n+1,2) ;
if (nlen-n==2) sn$=subString (snum,n+1,1)+"0" ;
if (nlen-n==0) sn$="00" ; //无小数
fn$=subString (snum,0,n) ; //截取整数部分
print "输入金额 snum = ", snum ;
// print "整数部分 fn = ", fn$ ; //test
// print "小数角分 sn = ", sn$ ;
//开始转换,先处理整数 fn$ ******
nlen=len (fn$) ; //字串长度
chb$=" " ; chs$=" " ;
for (i=0; i<nlen ; i++){
a$= subString (fn$, i,1 ) ;
snToD () ; //数字转大写 得c$
b$=subString (M$,nlen-i,1) ;
chb$=chb$+c$+b$ ; //整数已转换
}
if (sn$=="00") { //小数部分角分为零
chb$=chb$+"整" ;
goto result ; } //无小数转输出
//角分小数部分 ******
d1$=subString(sn$,0,1) ;
d2$=subString(sn$,1,1) ;
// print d1$ +" "+d2$ ; //test
if (d1$=="0" ){
c$="零" ; }else{
a$=d1$ ;
snToD ();
c$=c$+"角" ; }
d$ =c$ ;
if (d2$=="0" ){
c$="整" ; }else{
a$=d2$ ;
snToD ();
c$=c$+"分" ; }
d$ =d$+c$ ;
chs$=d$ ; //小数chs$已转换
//输出结果 ******
//上述计算已得到整数和小数部分的字串chb$ , chs$
//对于含零的位数需进一步处理。下面的算法可称为
// ”截数值位消零法”,或称 ”截位消零法” 。
result :
string pn$[20] ;
p$=" " ;
nlen=len (chb$)/2 ; //按中文二字组字串
for (i=0; i<20 ; i++){ pn$[i]=" " ; }
for (i=0; i<nlen ; i++){
pn$[i]=subString(chb$, i*2+1, 2) ; }
for (i=0; i<nlen ; i++){
p$=p$+pn$[i]+" " ; }
// print p$ ; //测试
//按位数处理 ”零” format **********
for (i=0; i<nlen ; i++){
p$=pn$[i] ;
if (p$=="零仟") { pn$[i]="零" ; }
if (p$=="零佰") { pn$[i]="零" ; }
if (p$=="零拾") { pn$[i]="零" ; }
if (p$=="零元") { pn$[i]="元" ; }
if (p$=="零万") { pn$[i]="万" ; }
if (p$=="零亿") { pn$[i]="亿" ; }
} //format
//处理连续位数零的整数部分 ******
chb$=" " ;
for (i=0; i<nlen ; i++){ //重组整数部分>去零
chb$=chb$+pn$[i] ; }
// print chb$+chs$ ; //测试
p$=" " ;
nlen=len (chb$) ;
for (i=0; i<20 ; i++){ pn$[i]=" " ; }
for (i=0; i<nlen ; i++){
pn$[i]=subString(chb$, i, 1) ; }
for (i=0; i<nlen ; i++){ //去多余 ”零”
p$=pn$[i] ;
if (p$=="零"&&pn$[i+1]=="零" ) { pn$[i]="" ; }
if (p$=="零"&&pn$[i+1]=="元" ) { pn$[i]="" ; }
if (p$=="零"&&pn$[i+1]=="万" ) { pn$[i]="" ; }
if (p$=="零"&&pn$[i+1]=="亿" ) { pn$[i]="" ; }
}
chb$=" " ;
for (i=0; i<nlen ; i++){ //去零后重组整数部分
chb$=chb$+pn$[i] ; }
//特殊情况100000902 大写: 壹亿万零玖佰零贰元整
//测试时碰到此例 ”壹亿万零... ” 要消 "万" ****
//string p1$, p2$ ;
nlen= len (chb$) ;
for (i=0; i<nlen ; i++){ //特殊情况
a$=subString (chb$, i, 1 ) ;
b$=subString (chb$, i+1, 1 ) ;
if (a$=="亿"&&b$=="万") {
a$=subString (chb$, 1, i) ;
b$=subString (chb$, i+2, nlen-i ) ;
chb$= a$+b$ ; } }
//输出结果 ******
// print " " ;
print " 大写输出:" ;
print chb$+chs$ ;
print "……………………………………...>" ;
}//exchange ()
snToD (){ //传入a$ 返回c$
N$="零壹贰叁肆伍陆柒捌玖" ;
if (a$=="0") c$=subString (N$,0,1) ;
if (a$=="1") c$=subString (N$,1,1) ;
if (a$=="2") c$=subString (N$,2,1) ;
if (a$=="3") c$=subString (N$,3,1) ;
if (a$=="4") c$=subString (N$,4,1) ;
if (a$=="5") c$=subString (N$,5,1) ;
if (a$=="6") c$=subString (N$,6,1) ;
if (a$=="7") c$=subString (N$,7,1) ;
if (a$=="8") c$=subString (N$,8,1) ;
if (a$=="9") c$=subString (N$,9,1) ;
}//snToD ()
sample (){
clearOutput ();
print "输出示例:" ;
snum="30600702" ;
exchange () ;
snum="1500903.08" ;
exchange () ;
snum="1020697.00" ;
exchange () ;
snum="159533.08" ;
exchange () ;
snum="282581697.50" ;
exchange () ;
snum="520967.56248" ;
exchange () ;
snum="2801697.00" ;
exchange () ;
}//sample()
test (){ //数值含零空位算法测试
clearOutput ();
print "特殊数值检测检验:" ;
snum="100000902" ;
exchange () ;
snum="20005600205" ;
exchange () ;
snum="3060002065" ;
exchange () ;
snum="10508005.75" ;
exchange () ;
snum="50700650.5" ;
exchange () ;
snum="1802065.06" ;
exchange () ;
snum="10502065.36" ;
exchange () ;
}//test ()
input (){//输入
string m;
snum=stringInput (" 输入金额转大写 "," 输入金额小写 例: 3572689.36 \n ( 输出金额大写 )\n 输入 [ 空 ] 退出 " ) ;
clearOutput ();
g$= subString (snum, 0 ,1 ) ;
//输入 "0.56" format > " .56"
if(g$=="0") snum= subString (snum,1, 3) ;
print "Input 金额 = ",snum ;
exchange ();
}//input ()
myToolBarProc(int nBtn,int nContext)
{
if(nBtn==100){//输入金额
input ();
}
if(nBtn==101){ //test 测试
test () ;
}
if(nBtn==102){//示例
sample ();
}
if(nBtn==103){//
//xxx xxx ();
}
if(nBtn==104){//退出程序
clearOutput();
exit (0);
}
}//myToolbar ()
//**** End ****