ACM训练2 : VIM

ACM训练2 : VIM

沉寂不,是拖更 了三天,除了沉迷于第五人格外只因这题对我来说十分难受,题目太长不想看,格式纷繁搞不清,思路全无憋不出······历经千辛万苦,终于断断续续地敲完了代码、删完了bug,在原题网址提交还超时了······
在这里插入图片描述
哦,后来发现又是一处bug,改完后就不超时啦!但是和其他Accepted大佬比起来我的代码还是有些冗长····大佬们有啥好方法还请不吝指教!!在这里插入图片描述

话不多说,进入正题:

古老的传闻余音淡袅,其中有一款传说级文本编辑器vim,此题既然敢起这样一个名称,想必定有相似之处。然而我没怎么用过,不知道相不相似。

题目来源:

HDU 3052,2009 Multi-University Tranining Contest 15-Host by BUAA
题目网址链接

题目描述:

本题只有一组输入数据。第一行包含一个正整数 L(L≤100),表示有一个包含L行文字的文本,接下来是L行文本,每行不超过100个字符。在文本之后是若干个(不超过50个)替换命令:[range]s/ {pattern} / {string} / [flag],命令中符号代表的含义如下:

  1. :表示替换命令的开始;
  2. [range]表示被操作的文本范围;
  3. s是substitude的简写,是替换的意思;
  4. {pattern}和{string}是要匹配的文本和将要替换成的文本;
  5. /用来作为分隔符;
  6. [flag]是一些操作的开关。

本题重要的规则和需要注意的事项说明如下:

  1. [range]一定会出现,为“%”(所有的行)或“a,b”(从第a行到第b行,a<b)。
  2. {pattern}和{string}只包含字母、数字、空格和下划线。
  3. 命令分割符包括/、~、!、@、#、$、%、^、&、*、()、-、+、=。
  4. [flag]只能是“g”,表示对出现的每个{pattern}都进行替换。
  5. 如果{pattern}为空,则使用上次不为空的{pattern}。
  6. 如果{pattern}是{string}的子串,不进行递归替换(这样永远替换不完)。
  7. 第i+1条命令处理的文本是由第i条命令处理后的文本。

输入样例:

4
If the Tao is greet, then the operating system is greet.
If the operating system is greeter, then the compiler is greet.
If the compiler is greeter, then the application is greet.
The user is pleased and there is harmony in the world.
:1,3s/greet/great/g
:%s//great/g

输出样例:

   1  If the Tao is great, then the operating system is great.
   2  If the operating system is greater, then the compiler is greater.
   3  If the compiler is greater, then the application is great.

Pattern not found

(由于markdown 不支持段首空格显示,所以这里用代码来显示,前三行开头三个空格,每行数字与文本之间有两个空格)

题目解析:

  1. 在输出中,两个替换命令的输出之间有一个空行。
  2. 文本输出格式:四个长度的后对齐行号,然后两个空格,之后就是文本
  3. 错误提示输出格式:顶格写起。
    (这些输出格式原题目中都已给出,好好看题是多么地重要啊呜呜呜)
  4. 如何从命令中获取替换范围?可以根据“s”的位置分为全选和自定义,自定义时两个行号之间有一个“,”,可以以此为中点,向左或向右遍历。
  5. 考虑到命令中各组是用“/”分隔的,所以想要找出{pattern}和{string}可以先找出“/”的位置,再得到{pattern}和{string}(就在两个“/”之间)。
  6. 命令中所给的{pattern}为空怎么办?如何替换为上一次的{pattern}?
  7. 考虑什么情况下会输出“Pattern not found”,第二次替换后输出呢,你的构想还成立吗?
  8. 如何替换文本?

参考代码

#include <iostream>
#include <string>
#include <iomanip>

using namespace std;
int startline,endline,n,s_position,p,p1,p2,p3;
char separator;
string text[100],command,lastreplace="",replaced,replaceby;
bool changed;

void search_command(int &s,int&e,string str){        //此函数用于从自定义替换范围的命令中
                                                       //读取替换的起始行数和结束行数
    int p = str.find(',');
    int sp = str.find(':');

    s = 0;
    e = 0;
    int length = str.length();
   for(int i=sp+1;i<p;i++){                          //考虑到行数可能不是个位数,最先读取的不一定是个位
        s *= 10;
        s += str[i]-'0';
   }
   for(int i=p +1;i<s_position;i++){
        e *= 10;
        e += str[i]-'0';
   }


}


int main()
{
    cin>>n;
    cin.get();                    //调用此函数,需要输入换行键以继续执行,以保证下面的getline()正确读取文本

    for(int i=1;i<=n;i++)  getline(cin,text[i]);
    int flag =  false ;          //用于判断是否是第一个命令,以便判断输出是=时是否需要换行
    lastreplace = "";
    while(getline(cin,command)){
        if(flag) cout<<endl;     //两个命令的输出之间间隔一个换行符
                                  //第一个命令的输出之前不用换行
        flag = true;
        s_position = command.find('s');
        if(s_position == 2)  {    //此时是全选状况:":%s"
            startline = 1;
            endline = n;
        }
        else search_command(startline,endline,command);     //自定义状况,调用之前的函数

        if(startline<1||endline>n)  return 0;
        
        p1 = s_position+1;
        separator = command[p1];                            //读取三个"/"的位置
        p2 = command.find(separator,p1+1);                  
        p3 = command.find(separator,p2+1);
        replaced = command.substr(p1+1,p2-p1-1);           //以此得出{pattern}和{string}
        replaceby = command.substr(p2+1,p3-p2-1);


        if(replaced == "")  replaced = lastreplace;        // 若{pattern}为空
        else lastreplace = replaced;
        
        changed = false ;                                  //用于判断此命令是否对文本进行了替换

        int re_len = replaced.length();                   //获取长度,为之后的替换作准备
        int reby_len = replaceby.length();

        for(int i=startline;i<=endline;i++){
            bool changedline = false;                    //用于判断本行是否被替换,以决定是否输出
                                                          //在替换范围内却未被替换的行是否要输出,我觉得无此必要
                                                          //原本的文本可以从输入中查找,这里只显示替换过后的文本更有效率
            p = text[i].find(replaced,0);
            while(p!=-1){
                text[i].replace(p,re_len,replaceby);
                changed = true;
                changedline = true;
                p = text[i].find(replaced,p+reby_len);
            }
            if(changedline)  cout<<setw(4)<<i<<"  "<<text[i]<<endl;

        }

        if(!changed) cout<<"Pattern not found"<<endl;    //没找到{pattern}的情况

    }
    return 0;



}

对不住各位啦,拖欠的我会慢慢补上的,相信我的人品!!

言而无信,不知其可。——《西游记》

ACM萌新拜上

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值