1033 旧键盘打字(20 分)
作者: CHEN, Yue
单位: 浙江大学
时间限制: 200ms
内存限制: 64MB
代码长度限制: 16KB
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及坏掉的那些键,打出的结果文字会是怎样?
输入格式:
输入在 2 行中分别给出坏掉的那些键、以及应该输入的文字。其中对应英文字母的坏键以大写给出;每段文字是不超过 105 个字符的串。可用的字符包括字母 [a
-z
, A
-Z
]、数字 0
-9
、以及下划线 _
(代表空格)、,
、.
、-
、+
(代表上档键)。题目保证第 2 行输入的文字串非空。
注意:如果上档键坏掉了,那么大写的英文字母无法被打出。
输出格式:
在一行中输出能够被打出的结果文字。如果没有一个字符能被打出,则输出空行。
输入样例:
7+IE.
7_This_is_a_test.
输出样例:
_hs_s_a_tst
这道题的思路大概是对于非字母、非+字符直接记录到散列表中即可,对于字母所有字母都按照小写字母记录,当上档键“+”出问题时将大写字母全部记录不可打印,然后在输出字母的时候就判断 tolower(字母) 和 字母本事是否可以输出,只有同时满足条件的时候才可以输出。这些是我的思路。
当然处理上档键的时候也可以判断是否为大写字母并且上档键是否出问题来决定是否输出,这是《算法笔记》中所给的思路。
这道题的思路不是关键问题,关键问题在于首行可能是一个空行,这时使用scanf来进行字符串的输入将会出问题,因为对于直接的空行 scanf 认为并不是有效输入,这时就让我想起来了已经好久没有祭出来的利器 —— gets
但是就在我以为已经解决的时候,使用c++的方式编译提交之后竟然说编译错误,错误就出在gets()那一行。
确认使用方法没有错误之后,改用过gets_s也不可以,最后查到可以使用 fgets() 来解决这一个问题
fgets的官方函数声明是:
char * fgets ( char * str, int num, FILE * stream );
在我们使用的时候第一个参数给定要输入的字符串,第二个参数给出这个字符串最大可输入的字符数,第三个字符串给出输入文件流,因为我们是从键盘输入,所以使用 标准输入流 stdin。
此时别以为这个问题已经解决了,还有一点需要注意:
可以从上面这段测试代码中看到,使用fgets并不像 gets那样是 输入字符串 + '\0' 组成,这里比输入字符串多了一个ascii值为10的字符 ,也就是 \n 所以最好把倒数第二个字符\n去掉,因为这可能会影响接下来的程序判断
使用:
int len = strlen(st);
if(st[len - 2] == '\n' && st[len - 1] == '\0') {
st[len - 2] = '\0';
}
即可将结尾的 \n 剔除
当然,如果使用 c 方式编译提交是可以使用gets的,并且还可以使用 c++ 中的getline执行相同的功能
好了问题彻底解决了,下面就是AC代码了。
AC代码:
#include <cstdio>
#include <ctype.h>
int main() {
bool c[200] = {0};
bool pri = false;
char broken[200], input[100010];
gets(broken);
scanf("%s", input);
for(int i = 0; broken[i] != '\0'; ++i) {
char ch = tolower(broken[i]);
if(ch == '+') {
for(int j = 0; j < 26; ++j) {
c[(int)('A' + j)] = true;
}
} else {
c[(int)ch] = true;
}
}
for(int i = 0; input[i] != '\0'; ++i) {
char ch = tolower(input[i]);
if(!c[(int)ch] && !c[(int)(input[i])]) {
printf("%c", input[i]);
pri = true;
}
}
if(!pri) {
printf("\n");
}
return 0;
}
如有错误,欢迎指摘。