问题描述
输入一个字符串,判断它是否为回文以及镜像串。输入字符串保证不含数字0.所谓回文串,就是反转之后原串相同,如abba和madam。所谓镜像串,就是左右镜像之后和原串相同,如2S和3AIAE。注意,并不是每个字符在镜像之后都能得到一个合法字符,本题中,每个字符的镜像如下所示,(空白项表示该字符镜像后不能得到一个合法的字符)。
#include<stdio.h>
#include<string.h>
#include<ctype.h>
const char* rev = "A 3 HIL JM O 2TUVWXY51SE Z 8 ";
const char* msg[] = {"not a palindrome", "a regular palindrome", "a mirrored string", "a mirrored palindrome"};
/*
这段代码是判断输入的字符是字母还是数字,使用一个自定义函数char r(char ch),
参数ch是一个字符,返回值是ch的镜像字符,因为该常量数组中前26项是各个大写字母的镜像,而后10个是1~9的数字
所以需要判断ch是字母还是数字,使用isalpha来判断字符是否为字母,在ctype.h中定义。
由于ASCII码表中大写字母、小写字母、数字都是连续的,如果ch是大写字母,则ch-'A'就是它在字母表中的序号(A序号是0,B为1,以此类推)
如果ch是数字,则ch-'0'就是这个数值本身 +25是因为前26项都是字母
*/
char r(char ch){
if(isalpha(ch)) return rev[ch-'A'];
return rev[ch-'0'+25];
}
int main(){
char s[30];
//scanf返回数据为读入数据的个数,==1表示在成功读入一个数据是执行循环
//scanf的返回值由后面的参数决定 scanf("%d%d", &a, &b); 如果a和b都被成功读入,那么scanf的返回值就是2
//如果只有a被成功读入,返回值为1 如果a和b都未被成功读入,返回值为0 如果遇到错误或遇到end of file,返回值为EOF。
// 且返回值为int型.
while(scanf("%s",s)==1){
int len = strlen(s);
int p=1,m=1;
for(int i=0; i<(len+1)/2; i++){
if(s[i]!=s[len-1-i]) p=0; //不是回文串
if(r(s[i])!=s[len-1-i]) m=0; //不是镜像串
}
printf("%s -- is %s.\n\n",s,msg[m*2+p]);
}
return 0;
}
输出msg[m*2+p]的原因
回文,镜像串,有4种组合。
msg[0]是: 非回文、非镜像。
msg[1]是: 回文、非镜像。
msg[2]是: 非回文、镜像。
msg[3]是: 回文、镜像。
为何最后输出的时候,m(镜像)要 * 2呢?
因为我们对比一下:msg[0],msg[1],这2个都是 非镜像,差别就在于回文,下标相关是1.再对比msg[2],msg[3],这2个都是镜像,差别就在于回文,相差是1.所以为何输出结果p * 1。
再对比msg[0], msg[2],都是非回文,差别就是 镜像与否,下标差了2. 最后对比msg[1],msg[3],都是回文,差别就是 镜像与否,下标相差2.所以为何输出结果m * 2.
贴出以下代码方便理解,可以用以下代码输出但显然会造成浪费
if(p==0&&m==0)
printf("%s----is %s\n\n",a,msg[0]);
if(p==1&&m==0)
printf("%s----is %s\n\n",a,msg[1]);
if(p==0&&m==1)
printf("%s----is %s\n\n",a,msg[2]);
if(p==1&&m==1)
printf("%s----is %s\n\n",a,msg[3]);