一、前言
写这篇博客的来源是一位名叫狗子的同学问了一个类似的问题,这应该是某个学校的c语言程序设计的填空题目吧?反正,那个时候看到题目花里胡哨的写法,用了四个指针,但是其实也是用到了双指针的想法,所以还是过来写下这一篇博客,一个解决那一个题目的思路,另外用STL内置函数find去实现这样的题目,当然目前只是测试了几个样例都对了,如果有什么错误的地方,欢迎广大读者及时纠正,我也会及时的改正的!!
二、题目描述
三、题目分析
大家可以看一看本题应当怎么思考,其实还是有一定的思考难度的,那么我们关注到的问题就是,为什么要利用四个指针?且最后输出应当怎么办呢?带着这样的疑问进行接下来的一个分析。至于具体的分析过程已经作为注释标在最终的代码里面了,大家可以一步一步跟着走。
四、完整代码
/*void fun(char s[],char c[]) //s表示原字符串,c表示要删除的子串
{
int i=0;
//q代表原字符串,q代表最终字符串,r代表待删除的子串,t用来过渡中间的删除过程
char *p,*q,*r,*t;
p=s;q=s;r=c;
while(*p) //p相当于从头到尾的遍历原字符串
{
while(*r!='\0'&&*p!='\0'&&*p==*r) //r进行每一次的子串删除
{
p++;r++;
}
//*******************************// if(*p=='\0') break; //原字符串遍历完毕直接跳出
if(*r=='\0') //代表在子串遍历过程中,原串产生了完全长度的子串
{
t=q; //t记录下来删除的那一瞬间q所指向的位置,便于之后的q移动后复原
while(*p) {*q=*p;p++;q++;} //此处是把删除某个子串之后的所有字符赋给q
*q='\0';q=t;p=q;r=c; //*q为'\0'代表在删完之后的串的最后加一个'\0'.
}
else //如果没有找到重复的,指针往后移动,子串重新指向首地址
{
q++;p=q;r=c;
}
}
q=s; //让最终输出的指针指向首地址
while(*q)
{
cout<<*q<<" ";
q++;
}
}
int main() //测试的程序
{
char s[10];
char c[3];
cin>>s;
cin>>c;
fun(s,c);
}
五、原题问题分析
在测试样例的时候,本蒟蒻发现,如果按照原本的思想进行的话,是没有办法删除后缀子串的。例如。
当我们删掉那一段之后 (if(*p=='\0') break;)结果便是这样的:
结果就对了,这是为什么呢?因为最外层的循环就是p!='\0'才会进行,但是如果删除最后的那一段子串,我们会发现,在进行while外层函数里面的第一个while之后,*p已经满足后面的break条件了,因此,直接跳出,不再进行后面的删除工作了,大家可以好好的看一看,走一走程序!
六、STL内置函数(find)的解法
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s,c,ans;
cin>>s>>c;
int p1=0,p2=s.find(c);
while(p1<s.length()) //p1小于s的总长度
{
if(p2==-1) //找不到就从p1位置一直复制到最后
{
for(int i=p1;i<s.length();i++)
ans+=s[i];
break; //跳出循环,不然是一个死循环
}
for(int i=p1;i<p2;i++)
ans+=s[i];
p1=p2+c.length(); //p1到了删除完之后的第一个位置
p2=s.find(c,p2+1); //p2从原本位置的下一个位置找后面待删除的子串
}
cout<<ans<<endl;
}
大家可以看到,利用内置函数解法的简便性,至于find的用法,下面也是自己学到的一些解法,仅供大家参考。