写这篇博客的来源是一位名叫狗子的同学问了一个类似的问题,这应该是某个学校的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条件了,因此,直接跳出,不再进行后面的删除工作了,大家可以好好的看一看,走一走程序!
#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的用法,下面也是自己学到的一些解法,仅供大家参考。