【题目描述】
输入一个三位数,分离出它的百位、十位和个位,反转后输出。
【样例输入】
127
【样例输出】
721
这个问题并不难,只需要两步:
①将这个三位数分离成三个数字(参见“整数的分离与合成”一文);
②反转三个数字的顺序输出。
代码如下:
#include<stdio.h>
int main(){
int n;
scanf("%d", &n);
printf("%d%d%d\n", n%10, n/10%10, n/100);
return 0;
}
不过这里面有两个容易被忽略的问题却值得讨论一下:
(1)-127是三位数吗?012呢?
数学中的定义:“位数”指一个自然数数位的个数,而“数位”是指一个数的每个数字所占的位置。
所以,我们说“n位数”就说明这个数首先是一个自然数,自然数(0和正整数)是用来表示自然界物体个数的数。-127不是自然数,也自然就不是三位数。
注意,以上结论完全是根据数学中“位数”的定义得来的,在算法竞赛中这样处理也是没问题的。
但是现实中你若没和人家提到负数,别人一般都想不到负数这回事,而一旦你提到了,他们可能就会忽然显现出一种豁然开朗的神情,大呼:“对呀,还得考虑负数的情况!”
你要是和他解释上面的数学定义,那他会不屑地反问:“那你说-127不是三位数是几位数?”
这句话会让你哑口无言(老金的儿子就是这样反问老金的,他对-127是三位数深信不疑。老金答不上他的问题,只好说让他去问老师)。
而012根本不是一个数,更不用谈是不是三位数了,因为数的最高位不能为0。
(2)数的最高位不能为0
“最高位不能为0”看似一句废话,但却经常被人忽略,甚至这道题本身就忽略了这一因素。
如果输入的三位数个位是0,反转后这个0要不要输出?比如,输入520,是要输出025还是25?因此这道题本身是不严谨的。
如果在算法竞赛中遇到这样的问题,可向监考人员询问,但在考试这种环境下,多半是无果的。
如果得不到回音,题还是要做的,这就要自己去分析:因为出题老师忽略了这个因素,就意味着可以对这个问题忽略不计,那就只管反转这三个数字就好了,不要考虑原数尾部是0的问题。
假如出题老师没有忽略这个问题,而且还有意在此设坑,他会怎么出题呢?
只需要对输出要求做一点小小的更改:把“反转后输出”改为“输出反转后的数。”
因为现在要求输出的是“数”,那么最高位肯定不能为0了,否则就不是“数”了。
修正后的问题怎么解呢?
如果不考虑对0的处理,整个程序可分为4步:输入、分离、反转、输出,这四步中,分离和反转都属于中间的“处理”环节。
分离和反转是对数的形式变换(不改变内容),而结果最高位不能为0是属于对数的内容的取舍。所以这种取舍过程应该放在生成结果之后,也就是放在反转之后。它有两个位置:输出前、输出时。
但其实还有另外一个思路,就是在输入之后、处理之前就对输入的数据进行预处理,去除数字尾部的所有零。这就像滤波器一样,滤掉数字的噪声。
所以,应记住对生成结果的处理可以放在以下三个环节:
①输入后;
②输出前;
③输出时。
1. 输入后:去除尾部所有0
首先,去除原数尾部所有0。比如输入520,500,在未分离、反转前就将尾部所有的0去掉,让其变为52、5,这样就保证了最后的结果最高位不是0。
然后,将去除尾部0的数反转输出。
程序如下:
#include<stdio.h>
int main(){
int n, m;
scanf("%d", &n);
//去除尾部所有0
while(n%10 == 0){
n /=10;
}
//利用“去尾法”反转输出
while(n>0){
printf("%d", n%10);
n/=10;
}
printf("\n");
return 0;
}
上述代码用了两个while循环,看起来有些难理解,但说到底无非还是用了%、/这两个运算符的两个功能:n%10:求尾数,n/10去尾数。
去除原数尾部所有0的方法:用n%10判断尾部的数是否为0,如果是0就用n/10去掉尾部数字。
将去除尾部0的数反转输出,正是利用了“取尾法”实现了整数的分离和反转(详见“整数的分离与合成”一文)。
这个程序的优点是适用范围广,几位数都可以。
2. 输出前:把反转结果转化为一个真正的数。
这种方法是在输出前把结果转化成一个整数,并存储在变量中。这样,直接用%d格式输出变量,最高位就不会再输出0。
#include<stdio.h>
int main(){
int n, m;
scanf("%d", &n);
m = n%10*100 + n/10%10*10 + n/100;
printf("%d\n", m);
return 0;
}
当然了,想要补上0也是可以的,只要把上面输出语中的%d改为%03d即可。即改成:
printf("%03d\n", m);
注:3代表输出的数要有3个数字,前面的0代表不满3个前面补0。
3. 输出时:根据条件选择性输出
思路很直接,就是在输出时加入判断。即依次检查要输出的数字的值,直到不为0时才开始输出。
#include<stdio.h>
int main(){
int n, units, tens, hundreds;
scanf("%d", &n);
units = n%10;// 获取个位
tens = n/10%10;// 获取十位
hundreds = n/100;// 获取百位
if(units != 0){
printf("%d%d%d\n", units, tens, hundreds);
} else if(tens !=0){
printf("%d%d\n", tens, hundreds);
} else{
printf("%d\n", hundreds);
}
return 0;
}
以上就是反转后去除高位0的三种方法,其中第1种代码理解相对有一定难度,不容易想到,但是适用范围广;第2、3种理解起来比较容易,但适用范围窄。