这几天正好在看字符串
在我不断的努力学习下,终于成功的
把代码完完整整一字不差的抄了下来,“嘿嘿”,可运行的时候,发现代码有错误???
我上当了??书本都是骗人的 还要我自己去debug 好家伙 好家伙
这究竟是道德的沦丧还是作者人性的泯灭 敬请观看下面代码
下面展示书上 代码
。
#include <stdio.h>
#include "string.h"
#define MAXLEN 40
typedef struct {
char ch[MAXLEN];
int len;
}SString;
int StrInsert(SString *s,int pos,SString t){
/*
pos为位置索引,t是插入的串.
*/
int i;
if(pos<0||pos>s->len) return false;
if(s->len+t.len<=MAXLEN){ //插入第一种情况,总长度小于MAXLEN.
for(i=s->len+t.len-1;i>=pos+t.len;i--)
s->ch[i]=s->ch[i-t.len];//先把插入位置后面字符串往后移动
for(i=0;i<t.len;i++)
s->ch[i+pos]=t.ch[i];//将插入的字符串进行插入
s->len=s->len+t.len;
}
else if(pos+t.len<=MAXLEN){/*插入第二种情况,插入后,后面一部分会被舍
弃,但插入部分不会被舍弃。*/
for(i=MAXLEN-1;i>t.len+pos-1;i--)
s->ch[i]=s->ch[i-t.len];//和上同理
for(i=0;i<t.len;i++)
s->ch[i+pos]=t.ch[i];
s->len=MAXLEN;
}
else {//第三种情况插入后,插入的字符串自身也被舍弃一部分。
for(i=0;i<MAXLEN-pos;i++)
s->ch[pos+i]=t.ch[i];
s->len=MAXLEN;
}
return true;
}
int StrDelete(SString *s,int pos,int len){//删除从pos开始,长度为len的子字符串。
int i;
if(pos<0||pos>(s->len-len)) return false;//不符合规则。
for(i=pos+len;i<s->len;i++){
s->ch[i-len]=s->ch[i];
}
s->len=s->len-len;
return true;
}
int StrCompare(SString s,SString t){
for(int i=0;i<s.len&&i<t.len,i++;)
if(s.ch[i]!=t.ch[i]) return (s.ch[i]-t.ch[i]);
return (s.len-t.len);
}
int main(){
SString ch1={"lzcstc",6};
SString ch2={",,,",3};
StrInsert(&ch1,3,ch2);
printf("%s\n",ch1.ch);
printf("%d\n",StrCompare(ch1,ch2) );
StrDelete(&ch1,1,3);
printf("%s\n",ch1.ch);
return 0;
}
调试结果:
奇怪了 说好删除1到3的子字符串 怎么后面还多了呢??
仔细看StrDelete那段代码
错误很明显 操作显然是把后面的字符往前移,那情况有三种:
1.后面那段代码的长度小于前面删除的长度
2.后面那段代码的长度大于前面删除的长度
3.后面那段代码的长度等于前面删除的长度
那么StrDelete成立的条件 居然一个也没有???
为什么?
因为只是数据往前移,本身存的那个数据还在,这就造成了重复,这就是我们上面的那种情况。并且前移的话,如果是条件1的情况下,那么前面的代码不能全部被后面覆盖,前面还会有多余。
解决方案
。
int StrDelete(SString *s,int pos,int len){
int i;
if(pos<0||pos>(s->len-len)) return false;
for(i=pos;i<pos+len;i++)
s->ch[i]=NULL;//这边前面要删除的数据
for(i=pos+len;i<s->len;i++){
s->ch[i-len]=s->ch[i];
s->ch[i]=NULL;//这边是后面要往前移的数据
}
s->len=s->len-len;
return true;
}
思路就是把前面要删除的先NULL,后面数据赋值完后再NULL,这样就避免了数据余留的问题了。