【算法】字符串-洛谷

P5015 [NOIP2018 普及组] 标题统计

NOIP2018 普及组] 标题统计 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

在怎么读取数据输入的问题上纠结了很久。

  • 本来想用cin>>x的形式一个字符一个字符地读,但发现不知道什么时候停止读取。
  • 改用scanf("%s",&s),但发现不能读取中间有空格的字符串(会被认为是两个字符串)。
  • 最终使用cin.getline(str, len),直接读取一行。

通过代码

#include<iostream>
using namespace std;
int main()
{
    int count=0;//标题中的字符数
    int LEN=20;
    char s[LEN]={};
    cin.getline(s, LEN);
    for(int i=0;i<LEN;i++)if((s[i]!='\0')&&(s[i]!=' ')&&(s[i]!='\n'))
        count++;
    cout<<count;
    return 0;
}

P5734 【深基6.例6】文字处理软件

P5734 【深基6.例6】文字处理软件 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

在插入字符串部分反复出bug。

  • 3 a str:插入片段,在文档中第a个字符前面插入字符串str,并输出文档的字符串。

思路是先腾出空位然后,然后填进要插入的字符串没错。但我想要在一个循环中完成,腾一个就填一个。后来发现思路是混乱了的,需要移动的字符串与需要填入的字符串长度并不一致。

如原字符串为abc,操作为3 0 d,我需要将三个字符各后移一位,但只需要填入一个字符d。

后来又遇到循环条件控制的问题,腾出空位时需要访问原字符串,我使用的代码如下。然而实际上随着字符串的后移,第一个\0的位置其实是在变化的,已经不是原来的字符串结尾了。而且我居然忘记了我是使用了一个int e;来指示字符串s的尾部的。

for(int i=0;s[i]!='\0';i++)s[e-1-i+len]=s[e-1-i]; //腾出空位

我将这一行代码修改如下,就通过了洛谷的测试。可能细心的读者已经发现了问题,“你怎么把整个字符串都后移了?”没错,虽然我成功过了洛谷的测试,但实际上使用的是一段有bug的代码

for(int i=0;i<e;i++)s[e-1-i+len]=s[e-1-i]; //腾出空位

这段含bug的完整代码如下:

#include<iostream>
#include<cstdio>
using namespace std;
void show(char s[], int e)//打印字符串 --> right
{
    for(int i=0;i<e;i++)printf("%c",s[i]);
    printf("\n");
}
void insert_end(char s[], int& e)//1 后接插入
{
    char str[100]={};
    scanf("%s",str);
    for(int i=0;str[i]!='\0';i++)s[e++]=str[i];
    show(s,e);
}
void get_part(char s[], int& e)//2 截取文档部分
{
    int a,b;//截取从a起的b个字符
    cin>>a>>b;
    for(int i=0;i<b;i++)s[i]=s[a+i];
    e=b;
    show(s,e);
}
void insert_front(char s[], int& e)//3 插入片段
{
    int a;
    char str[100]={};
    int len=0; // 插入字符串str的长度
    cin>>a;
    scanf("%s",str);
    for(int i=0;str[i]!='\0';i++)len++; //得到str长度
    for(int i=0;i<e;i++)s[e-1-i+len]=s[e-1-i]; //腾出空位
    for(int i=0;i<len;i++)s[a+i]=str[i]; // 插入字符
    e=e+len;
    show(s,e);
}
void find(char s[], int& e)
{
    char str[100]={};
    scanf("%s",str);
    for(int i=0;i<e;i++)
    {
        int flag=1;
        for(int j=0;str[j]!='\0';j++)if(s[j+i]!=str[j])
            flag=0;
        if(flag)
            {cout<<i<<endl;return;}
    }
    cout<<-1<<endl;
}
int main()
{
    char s[1000]={};//文档字符串
    int e=0;//s最后一个字符的下一个
    char str[100]={};//临时字符串
    int q=0;//操作次数
    int op=0;//操作类型
    cin>>q;
    scanf("%s",str);//输入初始文档
    for(int i=0;str[i]!='\0';i++)s[e++]=str[i];
    for(int i=0;i<q;i++)//q次操作
    {
        cin>>op;
        if(op==1)insert_end(s,e);
        else if(op==2)get_part(s,e);
        else if(op==3)insert_front(s,e);
        else if(op==4)find(s,e);
        else cout<<"error"<<endl;
    }
    return 0;
}

它在下面的测试中就发生了错误:

1
abcde
3 4 TT
ababTTe

只需要将腾出空位的代码修改如下,即可排除该bug。

for(int i=0;i<e-a;i++)s[e-1-i+len]=s[e-1-i]; //腾出空位
1
abcde
3 4 TT
abcdTTe
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值