1、getchar getline cin
getchar 逐个读取缓冲区内的字符
getline(cin, s) 读取输入流的一行字符(包含空格),并存入s
cin遇到空格停止
cin和getchar不读入字符后的换行符,会将其存入缓冲区,若cin/getchar后直接跟getline就会出问题,即getline首先读到的是换行符而非预期字符
因此在cin和getline之间可以使用getchar过滤回车
2、find rfind
find和rfind都能用来寻找特定字符,并返回其位置(从0开始)
find从前往后找、rfind从后往前找,但都是返回找到的元素的正向位置
当存在重复字符时,最先出现的位置使用find、最后出现的位置使用rfind
3、其他常用函数
erase(pos,n) 删除
insert(pos,str) 插入
replace(pos,n,str) 替换
transform(str.begin(),str.end(),str.begin(),::toupper/::tolower)整个字符串变大写/小写
(变大小写也可以str[i]-32或str[i]+32 相似的int+'0’会变为字符串,反之变为int)
for(int i=0;i<input.length();++i){
if(input[i]>='A'&&input[i]<='Z')
input[i]+=32;//大变小
else if(input[i]>='a'&&input[i]<='z')
input[i]-=32;//小变大
}
一、1509-3 模版生成
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
string in[105],var[105][2],temp,out[105];
int main(){
int m,n,start,end,flag=0;
cin>>m>>n;
getchar();//过滤回车
for(int i=0;i<m;++i)
getline(cin,in[i]);
for(int i=0;i<n;++i){
cin>>var[i][0];//遇空格停止
getline(cin,var[i][1]);
start=var[i][1].find("\"");//找双引号
end=var[i][1].rfind("\"");//反向找
var[i][1]=var[i][1].substr(start+1,end-start-1);
}
for(int i=0;i<m;++i){
while(1){
start=in[i].find("{{ ");
end=in[i].find(" }}");//不重复,直接正向找
if(start<0||end<0)
break;//{{ 或 }}不再存在时跳出当前循环
temp=in[i].substr(start+3,end-start-3);
for(int j=0;j<n;++j){
if(temp==var[j][0]){
flag=1;
temp=var[j][1];
break;
}
}
if(!flag)
temp="";
out[i]+=in[i].substr(0,start)+temp;
in[i]=in[i].substr(end+3,in[i].length()-end-3);
flag=0;
}
out[i]+=in[i];//加上后面剩的一截
cout<<out[i]<<endl;
}
return 0;
}
技巧:借助cin遇空格停止的性质,储存name、email、address等属性;注意find和rfind的使用场合(重复/不重复)
注意:输入的后n行是一定存在“”的,因此没有写if(start<0||end<0) 而前m行中可能存在没有{{ }}的情况,因此要先判断start和end的值,再取子字符串,即temp=in[i].substr(start+3,end-start-3);必须写在if判断语句之后,否则会出现运行错误
二、1703-3MK
遇到的困难有:
1、<p></p> <ul></ul>
的输出
2、#及*后面一个或多个空格对输出结果的影响
40分运行错误代码
#include <iostream>
using namespace std;
int main(){
string s;//input
string text="";//output;
bool flag;//前一行是否为段落或列表
while(getline(cin,s)){
if(s.find("_")!=-1){
s.replace(s.find("_"),1,"<em>");
s.erase(s.find("_"),1);
s.replace(s.find("_"),1,"</em>");
s.erase(s.find("_"),1);
flag-false;
}
if(s.find("#")!=-1){
int sum=0;
while(s[0]=='#'){
++sum;
s.erase(0,1);
}
while(s[0]==' ')
s.erase(0,1);
text+="<h",text+=(sum+'0'),text+=">"+s+"</h",text+=(sum+'0'),text+=">\n";
flag=false;
}
else if(s.find("*")!=-1){
s.erase(0,1);
while(s[0]==' ')
s.erase(0,1);
if(flag==false){//是第一行
text+="<ul>\n";
}
text+="<li>"+s+"</li>\n";
flag=true;
}
else if(s.find("[")!=-1){
int start=s.find("[");
int end=s.find("]");
string link=s.substr(start+1,end-start-1);
int start2=s.find("(");
int end2=s.find(")");
string href=s.substr(start2+1,end2-start2-1);
text+="<p>"+s.substr(0,start)+"<a href=\""+href+"\">"+link+"</a>\n";
flag=false;
}
else if(s.length()==0){
text+="0";
flag=false;
}
else{
if(flag==false){
text+="<p>";
}
text+=s+"\n";
flag=true;
}
}
while(text.find("0")!=-1){
int pos=text.find("0");
if(text[pos-2]!='>'&&text[pos-2]!='0'||text[pos-2]=='>'&&text[pos-3]=='a'){
text.erase(pos-1,1);
text.replace(pos-1,1,"</p>\n");
}
else
text.replace(pos,1,"~");
}
while(text.find("~")!=-1){
int pos=text.find("~");
if(text[pos-2]=='>'&&text[pos-3]=='i'){
text.replace(pos,1,"</ul>\n");
}
else
text.replace(pos,1,"");
}
if(text[text.length()-2]!='>'||text[text.length()-2]=='>'&&text[text.length()-3]=='a')
cout<<text.erase(text.length()-1,1)+"</p>";
else if(text[text.length()-2]=='>'&&text[text.length()-3]=='i')
cout<<text+"</ul>";
else
cout<<text;
return 0;
}
思路:
先得到不包括右标签的输出text,然后根据各种条件在text的基础上输出含右标签的完整text
错误原因可能是:
1、嵌套问题(是不是只需考虑强调和超链接之间的嵌套?还是说都要考虑?)
2、到底什么情况下使用<p></p>
(是否可以认为两行空格之间的非标题、非列表放在一对<p></p>中?)
如
hello world
*nihao
这种情况下的书写形式 </p>
是在world后面还是在</ul>
后面?
改进:
1、嵌套问题
标题、段落、列表中都可以嵌套超链接及强调
超链接和强调可以相互嵌套
解:可以通过对text再次遍历解决
改动:
先将输入中所有的强调部分变更为含<em>
标签对的形式
if(s.find("_")!=-1){
s.insert(s.find("_"),"<em>");
s.erase(s.find("_"),1);
s.insert(s.find("_"),"</em>");
s.erase(s.find("_"),1);
flag=false;
}
对输出的text再次遍历,处理嵌套超链接的问题
while(text.find("[")!=-1){
if(text.find("[")!=-1){
int start=text.find("[");
int end=text.find("]");
string link=text.substr(start+1,end-start-1);
int start2=text.find("(");
int end2=text.find(")");
string href=text.substr(start2+1,end2-start2-1);
string temp="<a href=\""+href+"\">"+link+"</a>";
text.replace(start,end2-start+1,temp);
}
}
这样改进后能得到70分,运行结果为“错误”
2、结果为错误的话,很大几率就是<p></p>
这里出问题了
考虑明天重写<p></p>
和<ul></ul>
部分??
3、当使用replace出现out of range错误时,可以用insert+erase的方式替代replace函数(见_变更为<em>
的处理)
三、1409-3 字符串匹配
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
string s,input;
int flag;
int n;
cin>>s>>flag>>n;
while(getline(cin,input)){
if(flag==1){
if(input.find(s)!=-1)
cout<<input<<endl;
}
else{
string temp=input;//不可省略
transform(s.begin(),s.end(),s.begin(),::toupper);
transform(input.begin(),input.end(),input.begin(),::toupper);
if(input.find(s)!=-1)
cout<<temp<<endl;
}
}
return 0;
}
四、1403-3 选择行选项
长题干题先提取题意
含两种参数:无参 -x,含参 -x (小写字母、数字、减号构成的非空)字符串
遇到非法参数则停止分析
输出格式为升序字母,含参选项要求同时输出参数;重复的参数仅输出一次,重复的含参参数仅输出最后一次出现时的参数