给你一个字符串S,要求你将字符串中出现的所有"gzu"(不区分大小写)子串删除,输出删除之后的S。
就是说出现“Gzu”、“GZU”、“GZu”、"gzU"都可以删除。
输入描述:
输入一行字符串S,长度不超过100。
输出描述:
输出进行删除操作之后的S。
输入样例:
GzzGzukkgzUuu
输出样例:
Gzzkkuu
**分析:**思路很简单,就是先把字符串全部转换成小写再进行模式匹配,删除对应的字串即可,但是实现方式不同。
本人本来想利用STL库中的find和erase实现快速的查找和删除,奈何遇到了大坑,代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
string s,flag;
cin>>s;
for(int i=0 ; i<s.length() ; i++){
flag[i]=s[i];
if(s[i]>='A'&&s[i]<='Z'){
s[i] = tolower(s[i]);
}
}
int site = s.find("gzu");
while(site>-1&&site+3<=s.length()){
s = s.erase(site,3);
flag = flag.erase(site,3);
site = s.find("gzu");
}
for(int k=0 ; k<s.length() ; k++){
cout<<flag[k];
}
return 0;
}
代码不长,但是却会遇到以下报错:
terminate called after throwing an instance of ‘std::out_of_range’ what(): basic_string::erase: __pos (which is 7) > this->size() (which is 0)
操作数位7但是s.size()=0,导致越界,这是什么原因造成的呢?前后两次赋值str的首地址极有可能是变化的。因为string里面的内存是动态分配的,想要赋值新的值,必须把上一次分配的空间收回,然后再分配更大的空间,所以首地址很有可能是变化的。可能被分配的地址还是上一个字符串的地址,所以导致越界。所以本人最终放弃了用这个方法。
最后还是使用了最原始的方法,巧妙之处是本人并没有把字串真正地从字符串中删除而是选择了牺牲空间换时间开辟一个标记数组来标记需要删除的位置,在cout时避开即可。 代码如下:
#include <bits/stdc++.h>
using namespace std;
char s[105]="gzu";
char t[105];
char t_lower[105];
int f[105];
int main (){
scanf("%s",&t);
int ls=strlen(s);
int lt=strlen(t);
for (int i=0;i<lt;i++){
if (t[i]>='A'&&t[i]<='Z')
t_lower[i]=tolower(t[i]);
else t_lower[i]=t[i];
}
for (int i=0;i<lt;i++){
int flag=0;
for (int j=0;j<ls;j++){
if(s[j]!=t_lower[i+j]) flag=1;
}
if (flag==0){
for (int j=i;j<i+ls;j++) f[j]=1;
}
}
for (int i=0;i<lt;i++){
if (f[i]==0) printf("%c", t[i]);
}
printf("\n");
return 0;
}
|