【题目描述】
把手放在键盘上时,稍不注意就会往右错一位。这样,输入Q会变成输入W,输入J会变成输入K等。键盘如图所示。
输入错位后敲出的几行字符串,输出打字员本来想打出的句子。
输入仅包含数字、空格、大写字母或标点符号,不包括带有英文单词的键(Tab, BackSp,Control等)。输入保证合法,即一定是错位之后的字符串,不会出现大写字母Q, A, Z及左上角的反引号“`”。
空格在输出中需正常显示。
注:原题说明有些含糊,上面是老金修改过的。
【样例输入】
O S, GOMR YPFSU/
【样例输出】
I AM FINE TODAY.
【题目来源】
刘汝佳《算法竞赛入门经典 第2版》例题3-2 WERTYU(WERTYU, UVa10082)
【解析】
原书代码:
#include<stdio.h>
char s[] = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./";
int main() {
int i, c;
while((c = getchar()) != EOF) {
for (i=1; s[i] && s[i]!=c; i++); //找错位之后的字符在常量表中的位置
if (s[i]) putchar(s[i-1]); //如果找到,则输出它的前一个字符
else putchar(c);
}
return 0;
}
代码说明:
1.读取函数的选择:如果每输入一个字符,都能通过某种规则直接求出要输出的字符(也就是说输出与输入的单个字符有关,与输入的单词、短语、句子无关),这种情况下用读取单个字符的函数getchar输入是理想的方法。
2.利用常量数组进行输入输出变换:这是本题的核心技巧。字符串本质上就是数组,因而可以利用数组下标建立起字符间的映射关系。因为需要判断的字符比较多,相比if或switch语句利用常量数组能大大减少代码量。而且,其可读性也更高,后续代码维护量也少。
严格来说,常量数组的元素均为常量,是不应被改变的,所以定义时应在类型名前加上const。不过本题重在理解常量数组的使用技巧,而不是讨论其定义,因而加不加无关紧要。
3.查找字符的位置。本题是通过遍历字符串来查找字符的位置的,这个功能也可以用strchr函数实现。该函数定义在 <string.h> 头文件中,strchr(s, c)的功能是在字符串s中查找字符c,如果找到,返回指向首次出现位置的指针。如果未找到,则返回 NULL。注意,它返回的是指向位置的指针,而不是位置的索引(数组下标)。用strchr函数修改的代码如下:
#include<stdio.h>
#include<string.h>
char s[] = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./";
int main() {
int c;
char *p;
while((c = getchar()) != EOF) {
if ((p=strchr(s,c))!= NULL) putchar(*(p-1)); //如果找到,则输出它的前一个字符
else putchar(c);
}
return 0;
}
4.输出单个字符:putchar是一个C标准库函数,用于输出单个字符。与之相关的另一个函数是puts,用于输出一个字符串(在输出字符串后会自动换行)。