#include<stdlib.h>
int next[50] //存储next值的数组
int nextval[50]
typedef struct
{
char *ch
int length //串长度
}HString
void StrAssign(HString *T,char *chars) //生成一个值等于串常量chars的串T
{
int i,j
char *c
if(T->ch)
free(T->ch) //释放T原有空间
for(i=0,c=chars*c++i,++c) //求chars长度
if(!i)
{
T->ch = NULL
T->length = 0
}
else
{
if(!(T->ch=(char*)malloc((i+1)*sizeof(char))))
exit(1)
for(j=0j<i++j)
T->ch[j] = chars[j]
T->ch[i] = '\0'
T->length = i
}
}
int StrLength(HString s) //返回S的元素个数,称串的长度
{
return s.length
}
int StrCompare(HString S,HString T) //串比较
{
//若S>T,则返回值>0若S=T,则返回值=0,若S<T,则返回值<0
int i
for(i=0i<S.length &&i<T.length++i)
if(S.ch[i]!=T.ch[i])
return S.ch[i] - T.ch[i]
return S.length - T.length
}
void ClearString(HString *S) //将S清为空串
{
if(S->ch)
{
free(S->ch)
S->ch = NULL
}
S->length = 0
}
void Concat(HString *T,HString s1,HString s2)
{
//用T返回由s1,s2联接而成的新串
int i,j
if(T->ch) free(T->ch) //释放旧空间
if(!(T->ch=(char*)malloc((s1.length+s2.length)*sizeof(char))))
exit(1)
T->length = s1.length + s2.length
for(i=0i<s1.length++i)
T->ch[i] = s1.ch[i]
for(j=0j<s2.length++j,++i)
T->ch[i] = s2.ch[j]
}
void SubString(HString *sub,HString s,int pos,int len)
{
//用sub返回串s的第pos个字符起长度为len的子串
//其中,1<=pos<=strlenth(s)且0<=len<=strlength(s)-pos + 1.
int i,j
if(pos<1 || pos>s.length || len<0 || len>s.length-pos+1)
{
printf("SubString's Location error!\n")
exit(1)
}
if(sub->ch) free(sub->ch)//释放旧空间
if(!len)
{
sub->ch = NULLsub->length = 0
}
else
{
sub->ch = (char*)malloc((len+1)*sizeof(char))
for(i=0,j=pos-1j<=pos+len-2++i,++j)
sub->ch[i] = s.ch[j]
sub->length = len
sub->ch[sub->length] = '\0'
}
}
void get_next(char *chars,int next[]) //生成next值的函数
{
int i,j,temp
i = 1
j = 0
next[1] = 0
while(chars[i])
{
if(j==0 &&i==1) //第二位的next应该都为1
{
++i++j
next[i] = j
}
else if(chars[i-1]!=chars[next[i]-1])//当测试next值上的数据与当前数据不等时进行
{
j = next[i] //取得next值
while(chars[j-1]!=chars[i-1]) //如当前的值,与下一next值也不同,j值继续后退
{
temp = j //取得前一next值
j = next[j]//前一next值
if(j<=0)
{
next[i+1] = 1
++i
break
}
else if(chars[j-1]==chars[i-1])
{
next[i+1] = next[temp] + 1//这里temp与J总是相隔一个位,所以是next[temp]
++i
break
}
}
}
else if(chars[i-1]==chars[next[i]-1]) //当测试next值上的数据与当前数据相等时进行
{
next[i+1] = next[i] + 1
++i
}
printf("next[%d]=%d\n",i,next[i])
}
}
void next_change(char *chars,int nextval[])
{
int i,j,temp
i = 1
nextval[1] = 0
for(j=1chars[j]++j)
{
temp = next[j+1]//取得当前的next[X]值
if(chars[j]==chars[temp-1]) //比较J位置上与相对于J位置的NEXT位上的元素值是否相等
{
nextval[j+1] = nextval[temp]//如相等则将前面的nextval值赋给当前nextval的值
}
else nextval[j+1] = temp //不相等则保留原next[]中的值
}
}
int Index(HString S,HString T,int pos)
{
int i,j
i = pos-1
j = 0
get_next(T.ch,next)
next_change(T.ch,nextval)
while(i<=S.length &&T.ch[j]) //字符串没到结尾不结束查找
{
if(S.ch[i]==T.ch[j])//相等则一起后移
{
i++j++
}
else if(S.ch[i]!=T.ch[j])
{
j = nextval[j+1]-1//不相等时取得next值-1因为
//next是按1,2,3...算所以要-1
if(j<=0 &&S.ch[i]!=T.ch[j])
{
i++//J移到next值上如值是<0则i向前移
j = 0//因为j可以变成小于0
}
}
}
if(j>=T.length) return i-T.length+1
else return 0
}
void StrInsert(HString *s,int pos,HString T) //在pos位置插入字符串T
{
int i,j
if(pos<1 || pos>(s->length+1))
{
printf("strInsert's Location error!\n")
exit(1)
}
if(T.length)
s->ch = (char*)realloc(s->ch,(s->length+T.length+1)*sizeof(char))//增加S的空间
for(j=s->lengthj>=pos-1--j) //POS位置到最后的字符往后移
s->ch[j+T.length] = s->ch[j]
for(i=0i<T.length++i) //T复制到S
{
s->ch[i+pos-1] = T.ch[i]
}
s->length = s->length + T.length
}
void StrDelete(HString *s,int pos,int len)//S存在,从S中删除第POS个字符起长度为LEN的子串
{
int i,j
if(pos<1 || pos>s->length-len)//判断删除位置是否合理
printf("delete Location error!\n")
else
{
for(i=pos+len-1,j=0i<s->length++i,++j) //删除中间元素,后面的元素往前移
s->ch[pos-1+j] = s->ch[i]
s->length = s->length - len
s->ch[s->length] = '\0'
}
}
void Replace(HString *s,HString t,HString v) //将V替换掉S中的T
{
int i
i = Index(*s,t,1)
while(i>0)
{
StrDelete(s,i,t.length)
StrInsert(s,i,v)
i = Index(*s,t,1)
}
}
void display(HString s)
{
printf("the string is :%s\n",s.ch)
}
int main(void)
{
HString obj,obj2,obj3,obj4
obj.ch = NULL//(char*)malloc(sizeof(char))
obj2.ch = NULL
obj3.ch = NULL
obj4.ch = NULL
StrAssign(&obj,"august")
StrAssign(&obj2,"yx")
StrAssign(&obj4,"ax")
display(obj)
display(obj2)
SubString(&obj3,obj,3,3)
display(obj3)
StrInsert(&obj3,1,obj2)
display(obj3)
Replace(&obj3,obj2,obj4)
display(obj3)
StrDelete(&obj3,1,3)
display(obj3)
return 0
}
你说的长短是指一行中的代码长短还是函数中的行数长短。不管怎么对编译器及运行机器来说现在已经没有或几乎没有区别了。区别主要是对人说的。而且长短也是相对的,没有固定值,多少算长多长算短。我一般一个函数的长度不超过一屏,就是能一次看完整个函数内容。这样来说短函中的内容可以一目了然,简单控制,并且容易可以重用。而长函数很简单出现多重嵌套,要看完要翻屏,严重影响理解而且相当容易出错。
如果你有过维护同事的几百行长函数代码经历的话,你就会深深的了解优缺点了。
程序是最老实的,你肯花时间肯定看的懂通常情况下,我的方法是同时了解全篇代码的流程注释上大块的功能,由于加了注释,就把长篇代码分成了功能块,最后就是理解这些功能块了。。。可能注释的时候会有错,但是不要紧,具体理解的时候可以再改正,最后就能分析出整个的原理了2:不能运行的话我一般先找出错误所在,将错误屏蔽,或者理解错误点的意思,然后跳过,继续看下面的代码。如果能屏蔽后运行,就照1的做,可能牵扯太多,改起来很浪费时间那就直接跳过,放弃自己的思路,直接理解作者的思路(个人觉得那样比较累),然后跟着走,还是同1以上说的重点,在于(1)理清功能实现思路,(2)浏览全篇代码,给自己一个流程印象只要知道大概作用就好,方便后面自己详细分析(4)分析理解每块功能代码,最后解析全篇以上个人意见和方法,希望对你有些帮助,希望不会再被评差贴。。。欢迎分享,转载请注明来源:内存溢出
评论列表(0条)