一、概述
给出一个不超过九位的数字,用拼音将它的汉语读法写出。
我觉得算是很复杂的一道题,它的复杂不在算法上的复杂,而在情况之多,极为复杂。
最开始的时候,我轻视了这道题,安安分分的一位一位向后移,取余,除十判断输出,但是在写的过程中发现许多种情况都需要判断,一项一项判断会弄得很晕,不知道什么时候该如何输出。然后才发现这道题的坑爹之处。这时候我已经被什么时候输出ling什么时候输出wan什么时候留空格什么时候不留弄晕了。于是狠下心来,采用了最稳妥也是最蠢最复杂的方法:将每一种情况都写出来,用if分别判断。写完之后我对着代码哭笑不得,这代码除了AC以外毫无优点,考场上肯定不会给我这么长的时间去梳理逻辑,我也很可能会落下几种情况,那样就gg了。效率也很是低下,而且很死板,变成十位十一位就不会输出了,可以说是完全的应试代码,鄙视自己。好在它逻辑清晰,很容易就可以看懂(废话,错误情况就再加一个if肯定清晰啊)。
坑点:
80008000(第二三四个零不输出ling)
0(输出ling)
8(输出ba)
100000000(输出yiyi)
80000008(输出baqianwanlingba)
800000008(输出bayilingba,没有wan)
二、分析
为了易于分析不同情况,我选择将数字全部变为十位,不足十位的补零,当然首位是符号位。
有以下几种情况:
我们以标志位为第0位,亿位为第一位,个位为第九位。
以第n位为例:
我们定义一个输出ling的标志位isZero,如果该标志位为1,那么说明前面已经输出过ling了,之后遇到0就不要输出ling,这是为了防止8008输出为八千零零八的情况。
如果该位非零,那么看它后面的所有位,
如果所有位都为零,输出的时候最后不加空格;
如果有至少一位不为零,那么输出的时候加空格;
之后置isZero为0,这说明后面遇到0要输出ling。
如果该位为零,那么看它后面所有位,
如果所有位都为零,不输出;
如果有至少一位不为零,那么继续判断isZero,
如果isZero为1,不输出;
如果isZero为0,输出ling;
之后置isZero为1,这说明后面遇到0不再输出ling。
代码如下:
case 6:
if (_num[6] != '0')//第六位如果不是零,直接输出,同时置输出ling标志位为0
{
if (_num[7] != '0' || _num[8] != '0' || _num[9] != '0')
cout << number[_num[i] - 48] << " " << "Qian ";
else
cout << number[_num[i] - 48] << " " << "Qian";
isZero = 0;
}
else
{
if (isZero == 1)
;
else
{
if (_num[7] != '0' || _num[8] != '0' || _num[9] != '0')
{
cout << "ling ";//输出ling
isZero = 1;//输出ling标志位置一
}
}
}
break;
case 7:
if (_num[7] != '0')//第七位如果不是零,直接输出,同时置输出ling标志位为0
{
if (_num[8] != '0' || _num[9] != '0')
cout << number[_num[i] - 48] << " " << "Bai ";
else
cout << number[_num[i] - 48] << " " << "Bai";
isZero = 0;
}
else
{
if (isZero == 1)
;
else
{
if (_num[8] != '0' || _num[9] != '0')
{
cout << "ling ";//输出ling
isZero = 1;//输出ling标志位置一
}
}
}
break;
case 8:
if (_num[8] != '0')//第八位如果不是零,直接输出,同时置输出ling标志位为0
{
if (_num[9] != '0')
cout << number[_num[i] - 48] << " " << "Shi ";
else
cout << number[_num[i] - 48] << " " << "Shi";
isZero = 0;
}
else
{
if (isZero == 1)
;
else
{
if (_num[9] != '0')
{
cout << "ling ";//输出ling
isZero = 1;//输出ling标志位置一
}
}
}
break;
特殊情况:
第二三四五位,不为零时输出都要加空格,因为这几位不为零时wan必定输出,wan后不加空格即可;
同时,三四五位有一位为零时,以第三位为零为例,
如果它后面有一位不为零,要判断不为零的这位是不是第四位第五位,
如果第四位第五位均为零,那么第三位的零也不输出ling,这是为了防止80000000输出为八千零万的情况。
代码如下:
case 2:
if (_num[2] != '0')//第二位如果是不是零,直接输出。eg.123456789
{
//if (_num[3] != '0' || _num[4] != '0' || _num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
//cout << number[_num[i] - 48] << " " << "Qian ";
//else
cout << number[_num[i] - 48] << " " << "Qian ";
isZero = 0;
}
else//第二位如果是零,那么如果第一位是零,则什么也不做;如果第一位不是零,继续判断。如果后面有非零数字,输出ling,否则,什么也不做。eg.123456789,103456789,100000000
{
if (_num[1] == '0')
;
else
{
if (_num[3] != '0' || _num[4] != '0' || _num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
{
cout << "ling ";//输出ling
isZero = 1;//输出ling标志位置一
}
}
}
break;
case 3:
if (_num[3] != '0')//第三位如果不是零,直接输出,同时置输出ling标志位为0
{
//if (_num[4] != '0' || _num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
//cout << number[_num[i] - 48] << " " << "Bai ";
//else
cout << number[_num[i] - 48] << " " << "Bai ";
isZero = 0;
}
else //第三位如果是零,继续判断
{
if (isZero == 1)//之前已经输出过ling了,即:这一位的0是一串连续的0中的不是第一个,eg.100456789,那么这个零就不用输出ling了
;
else//这说明这个0是第一个0,如果这个0后面还有非零数字,eg.120456789和120000000,输出ling,但是注意,80008000时,应该是八千万八千,不是八千零万八千
{
if (_num[4] != '0' || _num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
{
if (_num[4] == '0' && _num[5] == '0')
;
else
{
cout << "ling ";//输出ling
isZero = 1;
}//输出ling标志位置一
}
}
}
break;
case 4:
if (_num[4] != '0')//第四位如果不是零,直接输出,同时置输出ling标志位为0
{
//if (_num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
//cout << number[_num[i] - 48] << " " << "Shi ";
//else
cout << number[_num[i] - 48] << " " << "Shi ";
isZero = 0;
}
else
{
if (isZero == 1)
;
else//这说明这个0是第一个0
{
if (_num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
{
if (_num[5] == '0')
;
else
{
cout << "ling ";//输出ling
isZero = 1;
}//输出ling标志位置一
}
}
}
break;
第五位的wan,并不是所有的时候都输出的,
当第五位不为0时,要输出wan,
为零时,看第二三四位,
如果这三位都为零,那么wan就不输出,
如果不为零,那么第五位的零不输出,只输出wan。
代码如下:
case 5:
if (_num[5] != '0')//第五位如果不是零,直接输出,同时置输出ling标志位为0,注意第五位是特殊位,因为这个wan的输出有特例,如果2345位都是0,那么wan就不输出
{
if (_num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
cout << number[_num[i] - 48] << " " << "Wan ";
else
cout << number[_num[i] - 48] << " " << "Wan";
isZero = 0;
}
else
{
if (_num[2] == '0'&&_num[3] == '0'&&_num[4] == '0'&&_num[5] == '0')//2345位都是0,eg.100004567
;
else
{
if (_num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
cout << "Wan ";
else
cout << "Wan";
}
}
break;
第九位不为零时,正常输出,为零时,
如果前面全是零,那么输出ling,即输入的为0,
如果前面有一位不为零,那么不输出。
代码如下:
case 9:
if (_num[9] != '0')//第九位如果不是零,直接输出
cout << number[_num[i] - 48];
else
{
if(_num[1] == '0' && _num[2] == '0' && _num[3] == '0' && _num[4] == '0' && _num[5] == '0' && _num[6] == '0' && _num[7] == '0' && _num[8] == '0')
cout << number[_num[i] - 48];
}
break;
同时要注意isZero的初值应为1,这是为了防止8输出成零零八的情况。
这样一来,检查点应该可以全过了。
三、总结
本题逻辑分支较多,需要耐心梳理,梳理清楚也就好做得多了,使用多个标志位可以不必像我一样每位分别判断,但是总结出各种标志位也是不容易的。总而言之,自己AC还是很高兴的。就是看别人的代码只有几十行而我的有足足二百多行很是自卑(大括号换行顶了好多行呢)。
PS:代码如下
#include<stdio.h>
#include<string>
#include<iostream>
using namespace std;
char *ch[] = { "Fu","Yi","Qian","Bai","Shi","Wan","Qian","Bai","Shi","Ge"};
char *number[] = { "ling","yi","er","san","si","wu","liu","qi","ba","jiu" };
int main()
{
string num;
cin >> num;
char _num[10] = { '0','0','0','0','0','0','0','0','0','0'};
int m;
int length = num.length();
if (num[0] == '-')
{
_num[0] = '-';
for (m = length - 1; m > 0; m--)
{
_num[10 - length + m] = num[m];
}
}
else
{
for (m = length - 1; m >= 0; m--)
{
_num[10 - length + m] = num[m];
}
}//首先,把不足十位的数字通过在前面补零变成十位
int i;
int isZero = 1;
for (i = 0; i < 10; i++)
{
switch (i)
{
case 0:
if (_num[0] == '-')//是否是负数
cout << "Fu ";
break;
case 1:
if (_num[1] != '0')//第一位如果不是零,直接输出。eg.123456789
{
if(_num[2]!= '0' ||_num[3] != '0' || _num[4] != '0' || _num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
cout << number[_num[i] - 48] << " " << "Yi ";
else
cout << number[_num[i] - 48] << " " << "Yi";
isZero = 0;
}
break;//第一位如果是零,什么也不做
case 2:
if (_num[2] != '0')//第二位如果是不是零,直接输出。eg.123456789
{
//if (_num[3] != '0' || _num[4] != '0' || _num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
//cout << number[_num[i] - 48] << " " << "Qian ";
//else
cout << number[_num[i] - 48] << " " << "Qian ";
isZero = 0;
}
else//第二位如果是零,那么如果第一位是零,则什么也不做;如果第一位不是零,继续判断。如果后面有非零数字,输出ling,否则,什么也不做。eg.123456789,103456789,100000000
{
if (_num[1] == '0')
;
else
{
if (_num[3] != '0' || _num[4] != '0' || _num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
{
cout << "ling ";//输出ling
isZero = 1;//输出ling标志位置一
}
}
}
break;
case 3:
if (_num[3] != '0')//第三位如果不是零,直接输出,同时置输出ling标志位为0
{
//if (_num[4] != '0' || _num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
//cout << number[_num[i] - 48] << " " << "Bai ";
//else
cout << number[_num[i] - 48] << " " << "Bai ";
isZero = 0;
}
else //第三位如果是零,继续判断
{
if (isZero == 1)//之前已经输出过ling了,即:这一位的0是一串连续的0中的不是第一个,eg.100456789,那么这个零就不用输出ling了
;
else//这说明这个0是第一个0,如果这个0后面还有非零数字,eg.120456789和120000000,输出ling,但是注意,80008000时,应该是八千万八千,不是八千零万八千
{
if (_num[4] != '0' || _num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
{
if (_num[4] == '0' && _num[5] == '0')
;
else
{
cout << "ling ";//输出ling
isZero = 1;
}//输出ling标志位置一
}
}
}
break;
case 4:
if (_num[4] != '0')//第四位如果不是零,直接输出,同时置输出ling标志位为0
{
//if (_num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
//cout << number[_num[i] - 48] << " " << "Shi ";
//else
cout << number[_num[i] - 48] << " " << "Shi ";
isZero = 0;
}
else
{
if (isZero == 1)
;
else//这说明这个0是第一个0
{
if (_num[5] != '0' || _num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
{
if (_num[5] == '0')
;
else
{
cout << "ling ";//输出ling
isZero = 1;
}//输出ling标志位置一
}
}
}
break;
case 5:
if (_num[5] != '0')//第五位如果不是零,直接输出,同时置输出ling标志位为0,注意第五位是特殊位,因为这个wan的输出有特例,如果2345位都是0,那么wan就不输出
{
if (_num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
cout << number[_num[i] - 48] << " " << "Wan ";
else
cout << number[_num[i] - 48] << " " << "Wan";
isZero = 0;
}
else
{
if (_num[2] == '0'&&_num[3] == '0'&&_num[4] == '0'&&_num[5] == '0')//2345位都是0,eg.100004567
;
else
{
if (_num[6] != '0' || _num[7] != '0' || _num[8] != '0' || _num[9] != '0')
cout << "Wan ";
else
cout << "Wan";
}
}
break;
case 6:
if (_num[6] != '0')//第六位如果不是零,直接输出,同时置输出ling标志位为0
{
if (_num[7] != '0' || _num[8] != '0' || _num[9] != '0')
cout << number[_num[i] - 48] << " " << "Qian ";
else
cout << number[_num[i] - 48] << " " << "Qian";
isZero = 0;
}
else
{
if (isZero == 1)
;
else
{
if (_num[7] != '0' || _num[8] != '0' || _num[9] != '0')
{
cout << "ling ";//输出ling
isZero = 1;//输出ling标志位置一
}
}
}
break;
case 7:
if (_num[7] != '0')//第七位如果不是零,直接输出,同时置输出ling标志位为0
{
if (_num[8] != '0' || _num[9] != '0')
cout << number[_num[i] - 48] << " " << "Bai ";
else
cout << number[_num[i] - 48] << " " << "Bai";
isZero = 0;
}
else
{
if (isZero == 1)
;
else
{
if (_num[8] != '0' || _num[9] != '0')
{
cout << "ling ";//输出ling
isZero = 1;//输出ling标志位置一
}
}
}
break;
case 8:
if (_num[8] != '0')//第八位如果不是零,直接输出,同时置输出ling标志位为0
{
if (_num[9] != '0')
cout << number[_num[i] - 48] << " " << "Shi ";
else
cout << number[_num[i] - 48] << " " << "Shi";
isZero = 0;
}
else
{
if (isZero == 1)
;
else
{
if (_num[9] != '0')
{
cout << "ling ";//输出ling
isZero = 1;//输出ling标志位置一
}
}
}
break;
case 9:
if (_num[9] != '0')//第九位如果不是零,直接输出
cout << number[_num[i] - 48];
else
{
if(_num[1] == '0' && _num[2] == '0' && _num[3] == '0' && _num[4] == '0' && _num[5] == '0' && _num[6] == '0' && _num[7] == '0' && _num[8] == '0')
cout << number[_num[i] - 48];
}
break;
}
/*if (_num[i] == '0')
{
isZero = 1;
continue;
}
if (isZero == 1)
{
cout << "ling ";
isZero = '0';
}
if(i==0)
if (_num[0] == '-')
{
cout << "Fu ";
continue;
}
else
{
if (i != length - 1)
cout << number[_num[i] - 48] << " " << ch[length - i - 2];
else
cout << " " << number[_num[i] - 48];
}
if (_num[0] == '-')
{
if (length == 10)
{
if (i == 1)
cout << " Yi";
if (i == 5)
cout << " Wan";
}
if (length <= 9 && length >= 6)
if (i == length - 5)
cout << " Wan";
}
else
{
if (length == 9)
{
if (i == '0')
cout << " Yi";
if (i == 4)
cout << " Wan";
}
if (length <= 8 && length >= 5)
if (i == length - 5)
cout << " Wan";
}*/
}
}