郁闷的会计(非负整数转换成大写金额的拼音)

Problem Description

一天,一个小会计接到了一个重活,就是填写票据上的大写金额,这可把他忙得不可开交。

人民币大写金额的几条规则如下:
数字中 0~9 对应大写写法分别为:零壹贰叁肆伍陆柒捌玖(读音不变),且整个金额基本按照习惯上的读法来写。
数字金额上最高位为十位或十万位,且最高位上的数为「1」时,「壹」不可省略。如 15 元,大写金额格式为:壹拾伍元整。
数字金额中间有「0」时,大写金额要写「零」字。如 1024 元,大写金额格式为:壹仟零贰拾肆元整。
数字金额中间有连续的几个「0」时,大写金额中间只写一个「零」字,如 2008 元,大写金额格式为:贰仟零捌元整。
——相关规则摘自《正确填写票据和结算凭证的基本规定》,并根据题目需要稍作简化和修改

小会计从网上买到了一堆传说中能召唤出 ACMer 的「Accepted」标记,如果你能帮他完成数字金额转大写金额的任务,他会送给你一个的。
现在,他会提供给你数字金额,你只需要将转换后金额的拼音发给他就可以了。
Input

输入数据有多组(数据组数不超过 10000),到 EOF 结束。
每组数据输入一行,包含一个小于 1 亿的非负整数,代表要转换的数字金额。
Output

对于每组输入,输出一行,代表用拼音表示的转换后的大写金额。拼音之间用空格隔开。
Example Input

15
1024
2008
602333
9
7000999
10
1000
Example Output

yi shi wu yuan zheng
yi qian ling er shi si yuan zheng
er qian ling ba yuan zheng
liu shi wan ling er qian san bai san shi san yuan zheng
jiu yuan zheng
qi bai wan ling jiu bai jiu shi jiu yuan zheng
yi shi yuan zheng
yi qian yuan zheng
Hint

Author

「2016年第六届ACM趣味编程循环赛 Round #1」bLue
Think:字符串+循环的题。入手不难知道要对金额%取余,至0,中间的数据要存起来。我是把数据存在二维的字符串里,之后再根据大写金额的阅读方法来输出,这这点,是最大的难点。主要的是考虑金额中0出现的位置,比如1、10、101、100100等等数据,另外发现在0出现在“万”的前后还要进行一次特判(把情况考虑完整确实挺耗时间的,所以要耐心分析,首先根据题意要求以及题目里的样例的特殊情况的输出“提示”来完善自己考虑的情况)。

C语言代码如下:

#include
#include
int main()
{
    int n;
    while(scanf("%d", &n) != EOF){
        if(!n){  //先把金额为0的特殊情况解决
            printf("ling yuan zheng\n");
            continue;  
        }
        char s[110][110];  //根据题目数据范围,这个字符串数组可以再适当缩小
        int i = 1;
        while(n){
            switch(n % 10)
            {
                case 0:strcpy(s[i], "ling");break;  //赋值
                case 1:strcpy(s[i], "yi");break;
                case 2:strcpy(s[i], "er");break;
                case 3:strcpy(s[i], "san");break;
                case 4:strcpy(s[i], "si");break;
                case 5:strcpy(s[i], "wu");break;
                case 6:strcpy(s[i], "liu");break;
                case 7:strcpy(s[i], "qi");break;
                case 8:strcpy(s[i], "ba");break;
                case 9:strcpy(s[i], "jiu");break;
            }
            n /= 10; //例如N = 102, N/=10 之后N = 10
            if(n){  //如果此时N不为0
                i++;
                switch(i)
                {
                    case 2:strcpy(s[i], "shi");break;  //不解释
                    case 4:strcpy(s[i], "bai");break;
                    case 6:strcpy(s[i], "qian");break;
                    case 8:strcpy(s[i], "wan");break;
                    case 10:strcpy(s[i], "shi");break;
                    case 12:strcpy(s[i], "bai");break;
                    case 14:strcpy(s[i], "qian");break;
                    case 16:strcpy(s[i], "yi");break;
                }
                i++; //不要忘了,因为N尚且不为0,还要一波操作
            }
        }
        int len = i;
        for(i = len; i >= 1; i--){  //从字符串的尾部开始读取
            if(strcmp(s[i], "ling") == 0){ //当前为0的一波特判
                if(i == 1){                //建议自己先思考10分钟,在纸上                                         
                    break;               //列出情况再看看自己有没有漏情况
                }
                else if(strcmp(s[i - 1], "wan") == 0){
                    i--;
                    printf("%s ", s[i]);
                    if(strcmp(s[i - 1], "ling") != 0)
                        printf("ling ");
                }
                else if(strcmp(s[i - 2], "ling") == 0){
                    i--;
                }
                else{
                    printf("%s ", s[i]);
                    i--;
                }
            }
            else printf("%s ", s[i]);  //不为0“直接”输出
        }
        printf("yuan zheng\n");  //把“固定”的内容最后统一输出解决
    }
    return 0;
}

你可能感兴趣的:(模拟)