## 解题思路
先不考虑细枝末节,读几个数字可以发现,中文读法是从个位数字开始,每**四个**数字为一组来读的:如 25694123 读作 (二亿)(五千六百九十四万)(四千一百二十三)每一组都可以看作是:
几千几百几十几 + 亿/万/(空)整体思路便是将输入的数字(最多11位)分成三组,如图所示:
![](/image_editor_upload/20191107015834_49555.png)
每一块从左到右分别命名为“千”,“百”,“个”,“十”
一共需要3x4=12个容纳数字的空间,为了方便处理我们以字符串的形式输入,给'\0'腾出一个空间,所以创建字符数组:
```c
char num[13]; //字符数组
```
为了将数组的下标与“千”,“百”等单位更好地联系起来,我们将数字整体移动到数组的“尾部”,移动后'\0'在num[12]处。
![](/image_editor_upload/20191107011526_90473.png)
这样,亿级别的四位数对应num[0]~num[3]
万级别的四位数对应num[4]~num[7]
最后的四位数对应的是num[8]~num[11]
同样的,每一组的“千”对应的下标是0,4,8
“百”对应的是1,5,9
.......
可以发现,只要给定下标,就能确定其“级别”(亿,万)以及“单位”(千,百,个,十):
确定级别,只需用下标sub/4,如果为0,则是亿级别,为1,是万级别,为2,则是个级别
确定单位,只需用下标sub%4,如果为0,则是每组的“千”为,为1,则是“百位”,以此类推。
接下来则只用遍历这个字符数组,对每一个字符的下标进行“除4”和“余4”的操作,结合他本身的值便能读出 数值+单位 的组合
光做到这些也远远不够,有非常多的细节需要去考虑:
①“一十”与“十”
前者是 数值+单位 的组合,后者是仅仅只有单位。1010读作** 一千零一十** 而 100000 读作**十万**,而并非 一十万。我们发现,如果1是处在这个数字的最开始,且位于某组的十位时,那个 一 是不用读的,而对于不处于数字最开始位置的十位 一 是需要读成 一十的
②零的读法
可以说是这道题相对来说最困难的点
首先,每组个位的0是不读的,这点很好实现
其次,多个0连续的问题,多个0连续只读一次,或者不读,如10011000,前四个数字读成 一千零一万 连续的零读一次 后四个数字读成一千 连续的三个零一个都不读
究其原因,第一组中连续的零后面还有一个不为0的1,而第二组中后面三位数全部是0.所以确定0到底怎么读的具体思路是:
**读到0--从这个0开始扫描到这一组的末尾----设读0标志位为1(表示已经读了一次0)--读下一位--**
这样便能正确的读出数字中的0了
③“亿”和“万”读法
随便举个数字我们可以发现,“亿”是跟在第一组的个位后面的,而“万”是跟在第二组的个位后面的,比如,1500649302 读作一(第一组个位)**亿**五千零六(第二组个位)**万**九千三百零二(最后一组的个位后面不跟任何单位)
但有些情况,亿和万又不需要读,如100000000,中的万就没有读,是因为第二组为0000,全是0,所以不读,哪怕是0001,都要读成零一万,所以只需判断某组是否全为0即可。
细节考虑大概就这些,下面贴代码,写的不是太好,感觉有点复杂化了:
```c
#include#include#define size 13
int main()
{
int i,j,k,flag; //flag为读0标志位
char num[size]; //长度为13的字符串数组
scanf("%s",&num);
int length = strlen(num); //数字组的长度
int move_step , first_sub;
int info1 , info2; //第一个判断个十百千
int cz;
char c;
char *unit[3] = {"qian","bai","shi"};
char *bigunit[2] = {"yi","wan"};
char *a[10] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
/*整体移动数字到末尾*/
move_step = (size - 1) - length; //需要移动的步长
for(i = length ; i >= 0 ; i--)
{
num[i + move_step] = num[i];
num[i] = 0; //前面的空格取为0
}
/*开始从左到右遍历字符串*/
first_sub = move_step; //此时第一个元素的下标
flag = 0;
for(i = first_sub; i < size - 1 ; i++)
{
info1 = i%4;
info2 = i/4;
c = num[i];
cz = c - '0'; //c对应的整形值
/*info1 为0对应qian 1对应bai 2对应shi 3对应个位
info2 为0 个位处打印亿 为1 打印万*/
if(c != '0') {flag = 0;}
if(i == first_sub && info1 == 2 && c == '1')
printf("%s ", unit[2]); //开头十位的1不读 如100000读作十万而不是一十万
else if(c == '0' && info1 == 1 && (num[i + 1] != '0' || num[i + 2] != '0') && flag == 0) //flag为0接收读0
{ printf("%s ", a[cz]); flag = 1;}
else if(c == '0' && info1 == 2 && num[i + 1] != '0' && flag == 0) //flag为0接收读0
{ printf("%s ", a[cz]); flag = 1;}
else if(c == '0' && info1 == 0 && (num[i + 1] != '0' || num[i + 2] != '0' || num[i + 3] != '0') && flag == 0) //flag为0接收读0
{ printf("%s ", a[cz]); flag = 1;}
else if(c == '0' && length == 1) //单独输入为0的时候
{ printf("%s ",a[cz]);}
else if(info1 == 3) //个位
{
if(c == '0' && info2 == 0) //亿级别
printf("%s ", bigunit[info2]); //此时零不读 info2是0 打印yi
else if(c != '0' && info2 == 0)
printf("%s %s ", a[cz], bigunit[info2]);
if(c == '0' && info2 == 1 && (num[i - 1] != '0' || num[i - 2] != '0' || num[i - 3] != '0')) //万级别
printf("%s ", bigunit[info2]); //此时零不读 info2是1 打印wan
else if(c != '0' && info2 == 1)
printf("%s %s ", a[cz], bigunit[info2]);
else
;
if(c == '0' && info2 == 2)
printf("");
else if(c != '0' && info2 == 2)
printf("%s ",a[cz]); //此时个位后面不需要带什么单位
}
else if(c != '0')
printf("%s %s ",a[cz],unit[info1]);
}
return 0;
}
```
ac是没什么问题的,但是line9那里从键盘接收字符我最开始用的gets()函数,死活都过不了,显示答案错误12%
但改成scanf之后就过了,求哪位大佬评论区解答一下。。
0.0分
6 人评分