一、前言:
您好,我是夏日弥,本次为大家带来每周的例行PTA测试习题的讲解;
值得注意的是,笔者的编程水平有限,大部分的题目都不是最优解,如果您有更优秀的解决方案,请务必私信我,十分渴望向您学习;
本次带来五道编程题讲解;
涉及字符串string的使用,包括字符串遍历,拼接,字符串的整体输入;
涉及标记变量使用;
简单介绍string查找函数;
目录
感谢您的阅读,让我们来看看今天的题目吧;
二、例题部分;
2-1、字符串输入输出练习
字符串输入输出练习 (10 分)
输入起始位置m、长度l及字符串s,要求输出字符串s从第m个字符开始的长度为l的子串。
输入格式:
测试数据有多组,处理到文件尾。 每组测试数据输入一行,首先是以一个空格间隔的两个整数m、l,分别表示起始位置和长度,然后在一个空格之后是一个字符串s(长度不超过80,可能包含空格)。测试数据保证取得的结果字符串至少包含一个字符。
输出格式:
对于每组测试,输出字符串s从第m个字符开始的长度为l的子串(若长度不足l,则只需输出从第m个字符开始到最后一个字符结束的子串)。每两组测试数据之间留一个空行。
输入样例:
1 2 hello world!
9 6 welcome to acm world
输出样例:
he
to acm
2.2.1、题解
#include<bits/stdc++.h>
using namespace std;
int main() {
int n,m,p=0;//p为判断标记,判断是否为第一次输入;
while(scanf("%d %d",&n,&m)!=EOF){
string a;
getline(cin,a);
if(p!=0)cout<<endl<<endl;//如果不是第一次输入,就不输出换行,否则输出换行,确保测试用例之间有换行间隔;
p=1;//修改判断标记,读到这一行时表明第一次输入已经结束;
int top=n,end=top+m;//top为循环起点,end为循环终点;
while(top<end&&(top<=a.size()-1)){ //a.size()为a字符串的长度; //括号确保左边界top不会越过终点边界end,并且左边界不会超过字符串边界a.size()-1;
cout<<a[top];
top++;
}
}
}
这题属实是稀碎
难在格式问题,代码实现不难;
这里有个小细节:执行完 scanf("%d %d",&n,&m); 后
会直接执行getline(cin,a); a会直接读入你的空格,即此时的a为
“ hello world!”
而非
“hello world!”
所以我们的起点标记直接用 top=n;标识就可以了,如果您不喜欢的话,可以用getchar()来顶替掉那个空格,您的起点标记再标记为 top=n-1;就可以了
2-2 检查密码 (15 分)
本题要求你帮助某网站的用户注册模块写一个密码合法性检查的小功能。该网站要求用户设置的密码必须由不少于6个字符组成,并且只能有英文字母、数字和小数点 .
,还必须既有字母也有数字。
输入格式:
输入第一行给出一个正整数 N(≤ 100),随后 N 行,每行给出一个用户设置的密码,为不超过 80 个字符的非空字符串,以回车结束。
注意: 题目保证不存在只有小数点的输入。
输出格式:
对每个用户的密码,在一行中输出系统反馈信息,分以下5种:
- 如果密码合法,输出
Your password is wan mei.
; - 如果密码太短,不论合法与否,都输出
Your password is tai duan le.
; - 如果密码长度合法,但存在不合法字符,则输出
Your password is tai luan le.
; - 如果密码长度合法,但只有字母没有数字,则输出
Your password needs shu zi.
; - 如果密码长度合法,但只有数字没有字母,则输出
Your password needs zi mu.
。
输入样例:
5
123s
zheshi.wodepw
1234.5678
WanMei23333
pass*word.6
输出样例:
Your password is tai duan le.
Your password needs shu zi.
Your password needs zi mu.
Your password is wan mei.
Your password is tai luan le.
结尾无空行
2.2.1、题解
#include<bits/stdc++.h>
using namespace std;
int main(){
string a;
int n;
cin>>n;
getchar();
for(int i=0;i<n;i++){
int f1=0,f2=0,f3=0,f4=0;//f1记录是否有字母,f2记录是否有数字,f3记录是否有小数点,f4记录是否有非法字符
getline(cin,a);
if(a.size()<6){//判断密码够不够6位,不够就pass;
cout<<"Your password is tai duan le."<<endl;
}else{
//密码长度够了;
for(int i=0;i<a.size();i++){
if((a[i]>='a'&&a[i]<='z')||(a[i]>='A'&&a[i]<='Z'))f1=1;
else if(a[i]>='0'&&a[i]<='9')f2=1;
else if(a[i]=='.')f3=1;
else f4=1;
}
//遍历字符串,看看字符串有没有数字,字母,小数点,或者非法字符;
//f就像一个小灯泡,比如a【1】是数字,就拨亮f2的灯泡,没有的话它就一直是灭着的,是0;
if(f4==1){
cout<<"Your password is tai luan le."<<endl;
}else if(f1 == 1 && f2 == 1){
cout<<"Your password is wan mei."<<endl;
}else if(f1 == 1 && f2 == 0 ){
cout<<"Your password needs shu zi."<<endl;
}else if(f1 == 0 && f2 == 1 ){
cout<<"Your password needs zi mu."<<endl;
}
}
}
}
这道题的思想在于判断标记f1,f2,f3,f4;
我们的思路就是遍历字符串,对每一个字符记录它的性质,
如果是字母,我们就让f1=1,
如果是数字,我们就让f2=1,
如果是‘.’,我们就让f3=1,
如果它不是字母,数字,小数点,我们就让f4=1;
让f=1,就是拨亮小灯泡,表示我有!我真的有!否则它就是灭的,我没有......
对比2-1的标记变量,我们可以发现,标记变量的使用是很普遍的;我们一般把这种变量任命为flag或者_sucess,就像一个bool一样,0是错,是失败;1是对,是正确;
2-3 字符串-掐头去尾 (10 分)
输入字符串(长度大于2),删除首尾两个字符,输出结果字符串
输入格式:
键盘输入一个字符串,长度大于2小于80
输出格式:
去掉首尾两个字符后输出
输入样例:
在这里给出一组输入。例如:
abcdefgh
结尾无空行
输出样例:
在这里给出相应的输出。例如:
bcdefg
结尾无空行
2.3.1、题解
#include<bits/stdc++.h>
using namespace std;
int main(){
string a;
getline(cin,a);
for(int i=1;i<a.size()-1;i++)cout<<a[i];
}
水题,不多说;
2-4 字符替换 (10 分)
从键盘上输入一个字符串(最多80个字符),将其中所有的空格字符用字符“&”替换,然后输出替换后的字符串,最后换行。
输入格式:
从键盘上输入一个字符串(最多80个字符)。
输出格式:
输出替换后的字符串,最后换行。
输入样例:
ab cd ef gh
输出样例:
ab&cd&ef&gh
2.4.1、题解
#include<bits/stdc++.h>
using namespace std;
int main(){
string a;
getline(cin,a);
for(int i=0;i<a.size();i++){
if(a[i]==' ')cout<<"&";//遍历字符串,碰见“ ”输出“&”,否则输出啊a[i];
else cout<<a[i];
}
cout<<endl;
}
还是遍历一遍字符串,,,水题放后面我是不理解的。。。
不行,不能在这里摆大烂!给您展示一下字符串的拼接吧!
#include<bits/stdc++.h>
using namespace std;
int main(){
string a,res;
getline(cin,a);
for(int i=0;i<a.size();i++){
if(a[i]==' ')res+="&";//缝合怪出现了!,将“&”缝接到res上!
else res+=a[i]; //将a[i]连接到res上;
}
cout<<res<<endl;
}
2-5 字符串排序 (20 分)
本题要求编写程序,读入5个字符串,按由小到大的顺序输出。
输入格式:
输入为由空格分隔的5个非空字符串,每个字符串不包括空格、制表符、换行符等空白字符,长度小于80。
输出格式:
按照以下格式输出排序后的结果:
After sorted:
每行一个字符串
输入样例:
red yellow blue black white
结尾无空行
输出样例:
After sorted:
black
blue
red
white
yellow
结尾无空行
2.5.1、题解
#include<bits/stdc++.h>
using namespace std;
int main(){
string a[100];
int i=5;
for(int j=0;j<5;j++)cin>>a[j];
for(int j=0;j<i;j++){
for(int k=0;k<i-1;k++){
if(a[k]>a[k+1]){
string temp=a[k];
a[k]=a[k+1];
a[k+1]=temp;
}//如果a[k]>a[k+1],交换字符串a[k]与a[k+1];
//注意!!!!!知识点!!!!字符串的比较是按字典序比较的!!!
}
} //冒泡排序;
cout<<"After sorted:"<<endl;
for(int j=0;j<i-1;j++)cout<<a[j]<<endl;
cout<<a[i-1];
}
//注意!!!!!知识点!!!!字符串的比较是按字典序比较的!!!
字符串s1=“abcde”;
字符串s2=“bcd”;
计算机会先比对s1和s2第一个字符的ASCII码值;
因为‘b’的ASCII码值大于‘a’的,所以计算机认为s1>s2;
如果第一个字符一样,则比对第二个字符,称为“字典序比较”;
这道题涉及了字符串数组也得讲讲。。。。
是的,您没有看错!字符串就是那么好用,它不仅可以直接复制,拼接,调动丰富的函数,还允许开数组喔!
需要注意的是,您必须调用头文件<string.h>,否则您无法调动string;
string 变量名; 为声明一个string,可以不用声明长度,不像char[100],而且可以灵活伸长缩短;
介绍两个string小函数跟大家打声招呼吧:)
#include<bits/stdc++.h>
using namespace std;
int main(){
string a,b;
getline(cin,a);//完整读入字符串a,包含空格;
getline(cin,b);
cout<<a.size()<<endl;//输出a的长度,如"abc"会输出3;
a.find(b);//查找函数s1.find(s2),在字符串s1中查找子串s2,如"abc"是"abcdefg"的子串 ,
//查找成功则返回子串第一个字符的位置,如a的位置0;失败则返回 -1;
cout<<a.find(b);
}
getline(cin,a);//完整读入字符串a,包含空格;
cout<<a.size()<<endl;//输出a的长度,如"abc"会输出3;
a.find(b);//查找函数s1.find(s2),在字符串s1中查找子串s2,如"abc"是"abcdefg"的子串 ;
//查找成功则返回子串第一个字符的位置,如a的位置0;失败则返回 -1;
三、尾声
再次感谢您的阅读,本次题目代码均通过严格的样例测试;
但笔者难免精力有限,难免会发生错误;
如果您再阅读过程中有发现任何的bug,欢迎私信我或者在评论区留言,还望您不吝赐教;
特别鸣谢AC-47同学在2-1中提出的格式写法;
希望对您有所帮助,码字不易,如果您愿意点个赞,那将是夏日弥的无上荣光。
夏日弥死傲娇
2021.11.15