作者的话:若有朋友复制代码去PAT试着运行遇到问题的:
1.可能是格式问题,可以先把从本站复制的代码粘贴到记事本,再把记事本里的代码复制,然后粘贴到PAT的代码区,提交本题回答,应该就可以了;
2.可能是注释原因,PAT有时候检测到注释会编译错误,所以可以先把注释删了,再进行提交回答;
3.可能是作者当初根据题目写出来的代码仍存在一些疏漏,而恰好当时的测试机制没那么完善,没检测出问题。后面测试机制有所更新,故出现问题,若有相关需要的可以评论区留言或私信作者,我看到的话会去再查一下疏漏之处,然后更新文章。
一、题目描述
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及坏掉的那些键,打出的结果文字会是怎样?
输入格式:
输入在 2 行中分别给出坏掉的那些键、以及应该输入的文字。其中对应英文字母的坏键以大写给出;每段文字是不超过 105个字符的串。可用的字符包括字母 [a-z, A-Z]、数字 0-9、以及下划线 _(代表空格)、,、.、-、+(代表上档键)。题目保证第 2 行输入的文字串非空。
注意:如果上档键坏掉了,那么大写的英文字母无法被打出。
输出格式:
在一行中输出能够被打出的结果文字。如果没有一个字符能被打出,则输出空行。
输入样例:
7+IE.
7_This_is_a_test.
输出样例:
_hs_s_a_tst
二、解题思路
读题:
目标:给出两行输入,第一行代表电脑的哪些按钮坏了,第二行表示应该输入的文字,要求程序输出能够显示的文字。
字符列表:a-z A-Z 0-9 _ , . - +(成为坏键时所有大写字母无法显示)
思路:
1.定义需要的变量(存储两段输入文字的两个字符数组等);
2.输入接收(接收两个字符串);
3.字符检测。可以设置标志位flag,并设置循环对应该输入的文字序列中的每一个字符依次进行检测,每一轮循环检测一个字符,对于每一个字符,flag赋值为1,即默认可以显示。设置内层循环,将当前字符与坏键序列的每个字符进行比对(当然,如果当前字符是小写字母,需要在比对前进行转大写,这个可以使用库函数toupper()),若其和某个坏键比对成功,或者坏键序列中有’+’而当前字符恰好为大写,则把标志位flag置0(后面输出时将不会输出flag为0的字符);
4.输出显示。将标志位flag为1的字符进行输出(为了节省空间,标志位并不与每个字符绑定,只在每一轮循环供当前字符使用,所以对flag的判断和对字符的输出都会放在字符的检测循环中)。
三、具体实现
0.标准C源程序框架;
#include <stdio.h>
#include <string.h>//strlen()函数头文件
#include <ctype.h>//toupper(),isupper()函数头文件
int main()
{
return 0;
}
1.定义需要的变量(存储两段输入文字的两个字符数组等);
//1 变量预备
char not_work[100001],in[100001];//前者存储坏键序列,后者存储应该显示的文字序列
int i, j, len1, len2;//前两个变量是循环变量,后两个用于存储两个数组的有效长度,方便遍历两个数组
int flag;//字符是否能够显示的标志位
2.输入接收(接收两个字符串);
//2 输入接收
gets_s(not_work);
gets_s(in);
3.字符检测。可以设置标志位flag,并设置循环对应该输入的文字序列中的每一个字符依次进行检测,每一轮循环检测一个字符,对于每一个字符,flag赋值为1,即默认可以显示。设置内层循环,将当前字符与坏键序列的每个字符进行比对(当然,如果当前字符是小写字母,需要在比对前进行转大写,这个可以使用库函数toupper()),若其和某个坏键比对成功,或者坏键序列中有’+’而当前字符恰好为大写,则把标志位flag置0(后面输出时将不会输出flag为0的字符);
//3 字符检测
len1 = strlen(in);
len2 = strlen(not_work);
for (i=0;i<len1;i++)//对每个字符进行检测,循环体就是检测流程
{
flag = 1;//flag为1代表当前字符默认是可以显示的
for (j = 0; j < len2; j++)//遍历坏键序列,看是否有能和当前字符比对成功的坏键或能阻止当前字符显示的坏键
{
if (toupper(in[i]) == not_work[j])//如果当前字符为小写字母,则转大写,与坏键序列进行比对
{
flag = 0;//比对成功则将flag置0,表示当前字符无法显示,退出内层循环
break;
}
if (not_work[j] == '+' && isupper(in[i]) != 0)
{
//如果坏键序列中有上档键'+',且当前字符为大写字母(通过isupper()函数的返回值进行判断),
//则将flag置0,表示当前字符无法显示,退出内层循环
flag = 0;
break;
}
}
//4 输出显示(为了节省空间,标志位并不与每个字符绑定,只在每一轮循环供当前字符使用,
//所以对flag的判断和对字符的输出都会放在字符的检测循环中)
}
4.输出显示。将标志位flag为1的字符进行输出(为了节省空间,标志位并不与每个字符绑定,只在每一轮循环供当前字符使用,所以对flag的判断和对字符的输出都会放在字符的检测循环中)。
//4 输出显示
if (flag == 1)
{
printf("%c",in[i]);
}
四、测试数据
程序比较简单,一遍过了,没发现什么需要特别注意的测试数据,稍微关注一下题目说的“如果没有一个字符能被打出,则输出空行”和“如果上档键坏掉了,那么大写的英文字母无法被打出”这两句话就可以了。
五、全部代码
/*目标:给出两行输入,第一行代表电脑的哪些按钮坏了,第二行表示应该输入的文字,要求程序输出能够显示的文字。
字符列表:a-z A-Z 0-9 _ , . - +(坏了=所有大写字母无法显示)
*/
/*
步骤分解:
1 变量预备
2 输入接收
3 字符检测
4 输出显示*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
//1 变量预备
char not_work[100001],in[100001];//前者存储坏键序列,后者存储应该显示的文字序列
int i, j, len1, len2;//前两个变量是循环变量,后两个用于存储两个数组的有效长度,方便遍历两个数组
int flag;//字符是否能够显示的标志位
//2 输入接收
gets(not_work); //跟我一样喜欢用VS的,请注意,VS中gets()需要写作gets_s()
gets(in);
//3 字符检测
len1 = strlen(in);
len2 = strlen(not_work);
for (i=0;i<len1;i++)//对每个字符进行检测,循环体就是检测流程
{
flag = 1;//flag为1代表当前字符默认是可以显示的
for (j = 0; j < len2; j++)//遍历坏键序列,看是否有能和当前字符比对成功的坏键或能阻止当前字符显示的坏键
{
if (toupper(in[i]) == not_work[j])//如果当前字符为小写字母,则转大写,与坏键序列进行比对
{
flag = 0;//比对成功则将flag置0,表示当前字符无法显示,退出内层循环
break;
}
if (not_work[j] == '+' && isupper(in[i]) != 0)
{//如果坏键序列中有上档键'+',且当前字符为大写字母(通过isupper()函数的返回值进行判断),
//则将flag置0,表示当前字符无法显示,退出内层循环
flag = 0;
break;
}
}
//4 输出显示
if (flag == 1)
{
printf("%c",in[i]);
}
}
return 0;
}
六、优化代码(网上找到的,随便找了份代码都比我写得好,哭泣ing)
#include<stdio.h>
int main(void){
int i,wxx[1000]={0};//设置判断数组(注意初始化为零)
char wxxa[100001],wxxb[100001];//根据题目要求设置两数组大小储存输入字符串
gets(wxxa);
gets(wxxb);
for(i=0;wxxa[i]!='\0';i++){//遍历"坏键"数组改变目标数组元素的值
if(wxxa[i]>='A'&&wxxa[i]<='Z')//注意检测到大写字母要同时改变相应小写字母作下标的判断数组的值
wxx[wxxa[i]+32]=1;
wxx[wxxa[i]]=1;
}
for(i=0;wxxb[i]!='\0';i++){
if(wxx[wxxb[i]]!=1){
if(!(wxx['+']==1&&(wxxb[i]>='A'&&wxxb[i]<='Z')))//排除特殊情况输出(即"坏键"有上档键无法输入大写字母)
printf("%c",wxxb[i]);
}
}
return 0;
}