用C写个中文数字转换函数
如题,函数形式为:long Num(char str[]){...}
要求能实现如下转换:
"千">>1000
"五一二">>512
"二百三十">>230
"九十万">>900000
"十亿二百万零廿三">>1002000023
"万万">>100000000
大家来出出主意.
5L代码文曲星用,函数形式为long numch(int pt);
7L代码C用,函数形式为double numch(char *str);
[ 本帖最后由 LuoJun_LZ 于 2009-12-24 17:04 编辑 ] "五一二">>512
"二百三十">>230
仅两个就无法区分啊。你这个要求给得太模糊了。 这两个可以区分呀.
"五一二"中没有表示位数的文字,可用循环实现以下式子:
512=((5*10)+1)*10+2;
而"二百三十"中有两个表示位数的文字~~计算方式变为:
230=2*100+3*10
两种算法综合后,可把:
如"三五百一十"转为:3510 汗……原来是中文转阿拉伯数字啊。
我还以为是阿拉伯数字转中文=_= 汗,从函数形式就能看出来了呀~ 不过也可以弄个数字转中文的 :L 汗,都没什么人回应~~
我在文曲星上用LAV1写了一个,分享下:
char _NUMBER[]="零一壹二贰三叁四肆五伍六陆七柒八捌九玖十拾廿百佰千仟万兆亿";
long _Num(int pt1,int pt2,char len)//各位数字,位,位数
{//递归辅助函数
long tmp, i, a, btmp;
int w;//位数指针
char c;//指针
char k;
char t;
char tt;
w = len - 1;
while(w>=0)//逆序检测顺序是否由大到小
{
if(*(pt2+w-1)<=*(pt2+w))
{
c = w;
while(*(pt2+w-1)<=*(pt2+c) && w)
w--;
len = len - c + w;
memcpy(&tmp,pt1+c*4,4);//取升位数
memcpy(t,pt1+4+c*4,60-c*4);//移动
memcpy(tt,pt2+c,15-c);//移动
tmp = _Num(pt1+w*4,pt2+w,c-w)+tmp;//递归赋值
memcpy(pt1+w*4,&tmp,4);
memcpy(pt1+4+w*4,t,60-c*4);//移动
memcpy(pt2+w,tt,15-c);//移动
}
w--;
}
a = 0;
c = 0;
while(c<len)//计算
{
memcpy(&tmp,pt1+c*4,4);
k = *(pt2+c);
if(10 == k)
i = 10;
else
if(11 == k)
i = 20;
else
if(12 == k)
i = 100;
else
if(13 == k)
i = 1000;
else
if(14 == k)
i = 10000;
else
if(15 == k)
i = 1000000;
else
if(16 == k)
i = 100000000;
else
i = 1;
if(tmp)
a = a + i*tmp;
else
if(k)
a = a + i;
c++;
}
return a;
}
long numch(int pt)
{//转成非负整数
char x,k;
char w, len;
int b;
long num;
memset(num,0,64);
memset(w,0,16);
b = pt;
len = 0;
k = 1;
while(len<16 && *b)//循环1,取得数字代号
{
if(*b<128)
{
x = *b-'0';
if(x > 9)
break;
b--;
}
else
{
memcpy(&nc,b,2);
x = 0;
while(x<29 && (*b != _NUMBER || *(b+1) != _NUMBER))x++;//取得实际数字
if(x==29)
break;//遇到非数字字符
if(x<21)
x = x+1>>1;
else if(x==21)
x = 11;
else if(x<26)
x = x + 2 >>1;
else x = x - 12;
}
if(x>=10)
{
*(w+len)=x;
len++;
k = 1;
}
else
{
if(!x)
k = 0;
num = 10*num+x;//记录
}
b = 2 + b;
while(*b==' ')b++;//消除空格
if(*b ==',')b++;//遇到一个逗号
}
if(b == pt)
return -1;//出错
if(!len)//普通类型转换
return num;
if(num)
{
if(k)
if(!w)//处理如“二百五”=250的情况
if(w>12)
w = w-1;
else
if(w==12)
w = 10;
len ++;
}
return _Num(num,w,len);
}
//支持类型如:(实现中文大小写和阿拉伯数字混合使用)
//"1,000,000"=1000000;
//"1 2 3 45"=12345
//"一三五"=135
//"1百3十"=130;
//"五拾叁万"=530000
//"贰佰5"=250
//"贰佰05"=205
//"百万"=1000000
[ 本帖最后由 LuoJun_LZ 于 2009-12-22 16:24 编辑 ] 好样的。好久没人在WQX上写什么程序了 其实这个函数速度较慢,
文曲星上转换“一十九亿九千九百九十九万九千九百九十九”=1999999999
要0.26秒
又用C写了个,几乎完全注释:
#define MAX 16 //最大位数
char _NUMBER="零一壹二贰三叁四肆五伍六陆七柒八捌九玖十拾廿百佰千仟万兆亿";
double _Num(double *num,char *wei,char len)//各位对应数字,位,位数
{//递归辅助函数
double i, a, tmp;//临时数字
int w;//位数指针
char c;//指针
w = len - 1;
while(w>0)//逆序检测单位顺序是否由大到小,如“五千万五千”的单位顺序就不是由大到小
{
if(*(wei+w-1) <= *(wei+w))//前一个单位小于或等于后一个单位
{
c = w;//记录后一单位
w--;
while(*(wei+w-1)<=*(wei+c) && w)//检索到前一个单位大于记录单位为止
w--;
*(num+w) = _Num(num+w,wei+w,c-w) + *(num+c);//递归赋值
len = len - c + w;//长度收缩
for(char x=w+1;x<len;x++)//合并各位对应数值
*(num+x) = *(num+x+c-w);
for(x=w;x<len;x++)//合并位
*(wei+x) = *(wei+x+c-w);
}
w--;
}
a = 0;//临时计算用数
c = 0;
while(c<len)//计算
{
tmp = *(num+c);
switch(*(wei+c))
{
case 10: i = 10;break;
case 11: i = 20;break;
case 12: i = 100;break;
case 13: i = 1000;break;
case 14: i = 10000;break;
case 15: i = 1000000;break;
case 16: i = 100000000;break;
default : i = 1;
}
if(tmp)
a = a + i*tmp;
else
if(*(wei+c))
a = a + i;//将单位转换为数值
c++;
}
return a;
}
double numch(char *str)
{//转成非负整数
char wei={0};//位数记录
char len=0;//下标最大值
double num={0};
char x,k;//临时数据
char *t = str;//临时指针
while(len<MAX && *t)//循环,筛选整理
{
if(*t<='9' && *t>='0')//若是阿拉伯数字字符
{
x = *t - '0';//计算
t--;//阿拉伯数字只占一个字节
}
else
{
x = 0;
while(x<29 && (*t != *(_NUMBER+x*2) || *(t+1) != *(_NUMBER+x*2+1)))
x++;//检测比较中文字符
if(x==29)
break;//遇到非数字字符
if(x<21)
x = (x + 1) / 2;//0~9、十,代号10
else if(x==21)
x = 11;//廿,代号11
else if(x<26)
x = (x + 2) / 2;//百、千,代号12、13
else
x = x - 12;//万、兆、亿,代号14、15、16
}
if(x>=10)//遇到位代号记录位
{
*(wei+len)=x;//直接使用10~16作代号
len++;
k = 1;//k==1时关注如“二百五”==250的情况
}
else//遇到数字记录数字
{
if(!x)
k = 0;//遇到数字为0取消对“二百五”情况的关注
*(num+len) = *(num+len) * 10 + x;//每个位对应数字可以大于10
}
t += 2;//每个汉字占两个字节(阿拉伯数字已预先减1)
while(*t==' ')//其他处理,消除空格
t++;
if(*t ==',')//其他处理,遇到一个逗号
t++;
}
if(t == str)
return -1;//第一字符非数字字符
if(!len)//无单位类型返回
return num;
if(num)//不以0结尾
{
if(k)//关注“二百五”类型
if(!wei)//不以非“个”单位结尾
{
if(wei>12)//“千”及以上单位
*(wei+len) = *(wei+len-1) - 1;//单位降1
else
if(*(wei+len-1) == 12)//单位“百”降一位是“十”,11是“廿”的代号
*(wei+len) = 10;
}
len ++;//凡不以0结尾,计算位数要加1
}
return _Num(num,wei,len);//进入递归环节
}
//下面验证一下:
#include "stdio.h"
void main()
{
printf("一二三四五六七八九十>>%.0f\n",numch("一二三四五六七八九十"));
printf("壹贰叁肆伍陆柒捌玖拾>>%.0f\n",numch("壹贰叁肆伍陆柒捌玖拾"));
printf("1,2 3,4 5,6 7,8 9,0 >>%.0f\n",numch("1,2 3,4 5,6 7,8 9,0 "));
printf("一贰三肆五陆七捌九拾>>%.0f\n",numch("一贰三肆五陆七捌九拾"));
printf("1 贰3,肆 5陆,7捌 9拾>>%.0f\n",numch("1 贰3,肆 5陆,7捌 9拾"));
printf("5十万3百>>%.0f\n",numch("5十万3百"));
printf("1 六>>%.0f\n",numch("1 六"));
printf("1,000>>%.0f\n",numch("1,000"));
printf("一>>%.0f\n",numch("一"));
printf("贰>>%.0f\n",numch("贰"));
printf("百>>%.0f\n",numch("百"));
printf("十万>>%.0f\n",numch("十万"));
printf("九亿五百万肆千>>%.0f\n",numch("九亿五百万肆千"));
printf("2兆廿一>>%.0f\n",numch("2兆廿一"));
printf("2佰伍>>%.0f\n",numch("2佰伍"));
printf("2佰0伍>>%.0f\n",numch("2佰0伍"));
while(getchar()!='\n');
}
[ 本帖最后由 LuoJun_LZ 于 2009-12-24 17:06 编辑 ]
页:
[1]