CCF文本处理c++:1509-3模版生成 1703-3MK70分[日后看] 1409-3 字符串匹配

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 (小写字母、数字、减号构成的非空)字符串
遇到非法参数则停止分析
输出格式为升序字母,含参选项要求同时输出参数;重复的参数仅输出一次,重复的含参参数仅输出最后一次出现时的参数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值