- // bo4-1.cpp 串采用定长顺序存储结构(由c4-1.h定义)的基本操作(13个),包括算法4.2,4.3,4.5
- // SString是数组,故不需引用类型
- #define DestroyString ClearString // DestroyString()与ClearString()作用相同
- Status StrAssign(SString T,char *chars)
- { // 生成一个其值等于chars的串T
- int i;
- if(strlen(chars)>MAX_STR_LEN)
- return ERROR;
- else
- {
- T[0]=strlen(chars);
- for(i=1;i<=T[0];i++)
- T[i]=*(chars+i-1);
- return OK;
- }
- }
- void StrCopy(SString T,SString S)
- { // 由串S复制得串T
- int i;
- for(i=0;i<=S[0];i++)
- T[i]=S[i];
- }
- Status StrEmpty(SString S)
- { // 若S为空串,则返回TRUE,否则返回FALSE
- if(S[0]==0)
- return TRUE;
- else
- return FALSE;
- }
- int StrCompare(SString S,SString T)
- {// 初始条件:串S和T存在。操作结果:若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
- int i;
- for(i=1;i<=S[0]&&i<=T[0];++i)
- if(S[i]!=T[i])
- return S[i]-T[i];
- return S[0]-T[0];
- }
- int StrLength(SString S)
- { // 返回串S的元素个数
- return S[0];
- }
- void ClearString(SString S)
- { // 初始条件:串S存在。操作结果:将S清为空串
- S[0]=0; // 令串长为零
- }
- Status Concat(SString T,SString S1,SString S2) // 算法4.2改
- { // 用T返回S1和S2联接而成的新串。若未截断,则返回TRUE,否则FALSE
- int i;
- if(S1[0]+S2[0]<=MAX_STR_LEN)
- { // 未截断
- for(i=1;i<=S1[0];i++)
- T[i]=S1[i];
- for(i=1;i<=S2[0];i++)
- T[S1[0]+i]=S2[i];
- T[0]=S1[0]+S2[0];
- return TRUE;
- }
- else
- { // 截断S2
- for(i=1;i<=S1[0];i++)
- T[i]=S1[i];
- for(i=1;i<=MAX_STR_LEN-S1[0];i++)
- T[S1[0]+i]=S2[i];
- T[0]=MAX_STR_LEN;
- return FALSE;
- }
- }
- Status SubString(SString Sub,SString S,int pos,int len)
- { // 用Sub返回串S的第pos个字符起长度为len的子串。算法4.3
- int i;
- if(pos<1||pos>S[0]||len<0||len>S[0]-pos+1)
- return ERROR;
- for(i=1;i<=len;i++)
- Sub[i]=S[pos+i-1];
- Sub[0]=len;
- return OK;
- }
- int Index(SString S,SString T,int pos)
- { // 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0。
- // 其中,T非空,1≤pos≤StrLength(S)。算法4.5
- int i,j;
- if(1<=pos&&pos<=S[0])
- {
- i=pos;
- j=1;
- while(i<=S[0]&&j<=T[0])
- if(S[i]==T[j]) // 继续比较后继字符
- {
- ++i;
- ++j;
- }
- else // 指针后退重新开始匹配
- {
- i=i-j+2;
- j=1;
- }
- if(j>T[0])
- return i-T[0];
- else
- return 0;
- }
- else
- return 0;
- }
- Status StrInsert(SString S,int pos,SString T)
- { // 初始条件:串S和T存在,1≤pos≤StrLength(S)+1
- // 操作结果:在串S的第pos个字符之前插入串T。完全插入返回TRUE,部分插入返回FALSE
- int i;
- if(pos<1||pos>S[0]+1)
- return ERROR;
- if(S[0]+T[0]<=MAX_STR_LEN)
- { // 完全插入
- for(i=S[0];i>=pos;i--)
- S[i+T[0]]=S[i];
- for(i=pos;i<pos+T[0];i++)
- S[i]=T[i-pos+1];
- S[0]+=T[0];
- return TRUE;
- }
- else
- { // 部分插入
- for(i=MAX_STR_LEN;i>=pos+T[0];i--)
- S[i]=S[i-T[0]];
- for(i=pos;i<pos+T[0]&&i<=MAX_STR_LEN;i++)
- S[i]=T[i-pos+1];
- S[0]=MAX_STR_LEN;
- return FALSE;
- }
- }
- Status StrDelete(SString S,int pos,int len)
- { // 初始条件:串S存在,1≤pos≤StrLength(S)-len+1
- // 操作结果:从串S中删除第pos个字符起长度为len的子串
- int i;
- if(pos<1||pos>S[0]-len+1||len<0)
- return ERROR;
- for(i=pos+len;i<=S[0];i++)
- S[i-len]=S[i];
- S[0]-=len;
- return OK;
- }
- Status Replace(SString S,SString T,SString V) // 此函数与串的存储结构无关
- { // 初始条件:串S,T和V存在,T是非空串
- // 操作结果:用V替换主串S中出现的所有与T相等的不重叠的子串
- int i=1; // 从串S的第一个字符起查找串T
- Status k;
- if(StrEmpty(T)) // T是空串
- return ERROR;
- do
- {
- i=Index(S,T,i); // 结果i为从上一个i之后找到的子串T的位置
- if(i) // 串S中存在串T
- {
- StrDelete(S,i,StrLength(T)); // 删除该串T
- k=StrInsert(S,i,V); // 在原串T的位置插入串V
- if(!k) // 不能完全插入
- return ERROR;
- i+=StrLength(V); // 在插入的串V后面继续查找串T
- }
- }while(i);
- return OK;
- }
- void StrPrint(SString T)
- { // 输出字符串T。另加
- int i;
- for(i=1;i<=T[0];i++)
- printf("%c",T[i]);
- printf("/n");
- }
- // bo4-2.cpp 串采用堆分配存储结构(由c4-2.h定义)的基本操作(14个)。包括算法4.1、4.4
- #define DestroyString ClearString // DestroyString()与ClearString()作用相同
- void StrAssign(HString &T,char *chars)
- { // 生成一个其值等于串常量chars的串T
- int i,j;
- if(T.ch)
- free(T.ch); // 释放T原有空间
- i=strlen(chars); // 求chars的长度i
- if(!i)
- { // chars的长度为0
- T.ch=NULL;
- T.length=0;
- }
- else
- { // chars的长度不为0
- T.ch=(char*)malloc(i*sizeof(char)); // 分配串空间
- if(!T.ch) // 分配串空间失败
- exit(OVERFLOW);
- for(j=0;j<i;j++) // 拷贝串
- T.ch[j]=chars[j];
- T.length=i;
- }
- }
- void StrCopy(HString &T,HString S)
- { // 初始条件:串S存在。操作结果:由串S复制得串T
- int i;
- if(T.ch)
- free(T.ch); // 释放T原有空间
- T.ch=(char*)malloc(S.length*sizeof(char)); // 分配串空间
- if(!T.ch) // 分配串空间失败
- exit(OVERFLOW);
- for(i=0;i<S.length;i++) // 拷贝串
- T.ch[i]=S.ch[i];
- T.length=S.length;
- }
- Status StrEmpty(HString S)
- { // 初始条件:串S存在。操作结果:若S为空串,则返回TRUE,否则返回FALSE
- if(S.length==0&&S.ch==NULL)
- return TRUE;
- else
- return FALSE;
- }
- int StrCompare(HString S,HString T)
- { // 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
- int i;
- for(i=0;i<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;
- }
- int StrLength(HString S)
- { // 返回S的元素个数,称为串的长度
- return S.length;
- }
- void ClearString(HString &S)
- { // 将S清为空串
- free(S.ch);
- S.ch=NULL;
- S.length=0;
- }
- void Concat(HString &T,HString S1,HString S2)
- { // 用T返回由S1和S2联接而成的新串
- int i;
- if(T.ch)
- free(T.ch); // 释放旧空间
- T.length=S1.length+S2.length;
- T.ch=(char *)malloc(T.length*sizeof(char));
- if(!T.ch)
- exit(OVERFLOW);
- for(i=0;i<S1.length;i++)
- T.ch[i]=S1.ch[i];
- for(i=0;i<S2.length;i++)
- T.ch[S1.length+i]=S2.ch[i];
- }
- Status SubString(HString &Sub, HString S,int pos,int len)
- { // 用Sub返回串S的第pos个字符起长度为len的子串。
- // 其中,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1
- int i;
- if(pos<1||pos>S.length||len<0||len>S.length-pos+1)
- return ERROR;
- if(Sub.ch)
- free(Sub.ch); // 释放旧空间
- if(!len) // 空子串
- {
- Sub.ch=NULL;
- Sub.length=0;
- }
- else
- { // 完整子串
- Sub.ch=(char*)malloc(len*sizeof(char));
- if(!Sub.ch)
- exit(OVERFLOW);
- for(i=0;i<=len-1;i++)
- Sub.ch[i]=S.ch[pos-1+i];
- Sub.length=len;
- }
- return OK;
- }
- void InitString(HString &T)
- { // 初始化(产生空串)字符串T。另加
- T.length=0;
- T.ch=NULL;
- }
- int Index(HString S,HString T,int pos) // 算法4.1
- { // T为非空串。若主串S中第pos个字符之后存在与T相等的子串,
- // 则返回第一个这样的子串在S中的位置,否则返回0
- int n,m,i;
- HString sub;
- InitString(sub);
- if(pos>0)
- {
- n=StrLength(S);
- m=StrLength(T);
- i=pos;
- while(i<=n-m+1)
- {
- SubString(sub,S,i,m);
- if(StrCompare(sub,T)!=0)
- ++i;
- else
- return i;
- }
- }
- return 0;
- }
- Status StrInsert(HString &S,int pos,HString T) // 算法4.4
- { // 1≤pos≤StrLength(S)+1。在串S的第pos个字符之前插入串T
- int i;
- if(pos<1||pos>S.length+1) // pos不合法
- return ERROR;
- if(T.length) // T非空,则重新分配空间,插入T
- {
- S.ch=(char*)realloc(S.ch,(S.length+T.length)*sizeof(char));
- if(!S.ch)
- exit(OVERFLOW);
- for(i=S.length-1;i>=pos-1;--i) // 为插入T而腾出位置
- S.ch[i+T.length]=S.ch[i];
- for(i=0;i<T.length;i++)
- S.ch[pos-1+i]=T.ch[i]; // 插入T
- S.length+=T.length;
- }
- return OK;
- }
- Status StrDelete(HString &S,int pos,int len)
- { // 从串S中删除第pos个字符起长度为len的子串
- int i;
- if(S.length<pos+len-1)
- return ERROR;
- for(i=pos-1;i<=S.length-len;i++)
- S.ch[i]=S.ch[i+len];
- S.length-=len;
- S.ch=(char*)realloc(S.ch,S.length*sizeof(char));
- return OK;
- }
- Status Replace(HString &S,HString T,HString V) // 此函数与串的存储结构无关
- { // 初始条件:串S,T和V存在,T是非空串
- // 操作结果:用V替换主串S中出现的所有与T相等的不重叠的子串
- int i=1; // 从串S的第一个字符起查找串T
- if(StrEmpty(T)) // T是空串
- return ERROR;
- do
- {
- i=Index(S,T,i); // 结果i为从上一个i之后找到的子串T的位置
- if(i) // 串S中存在串T
- {
- StrDelete(S,i,StrLength(T)); // 删除该串T
- StrInsert(S,i,V); // 在原串T的位置插入串V
- i+=StrLength(V); // 在插入的串V后面继续查找串T
- }
- }while(i);
- return OK;
- }
- void StrPrint(HString T)
- { // 输出T字符串。另加
- int i;
- for(i=0;i<T.length;i++)
- printf("%c",T.ch[i]);
- printf("/n");
- }
- // bo4-3.cpp 串采用块链存储结构(由c4-3.h定义)的基本操作(15个)
- #define DestroyString ClearString // DestroyString()与ClearString()作用相同
- void InitString(LString &T)
- { // 初始化(产生空串)字符串T。另加
- T.curlen=0;
- T.head= T.tail=NULL;
- }
- Status StrAssign(LString &T,char *chars)
- { // 生成一个其值等于chars的串T(要求chars中不包含填补空余的字符)。成功返回OK,否则返回ERROR
- int i,j,k,m;
- Chunk *p,*q;
- i=strlen(chars); // i为串的长度
- if(!i||strchr(chars,blank)) // 串长为0或chars中包含填补空余的字符
- return ERROR;
- T.curlen=i;
- j=i/CHUNK_SIZE; // j为块链的结点数
- if(i%CHUNK_SIZE)
- j++;
- for(k=0;k<j;k++)
- {
- p=(Chunk*)malloc(sizeof(Chunk)); // 生成块结点
- if(!p) // 生成块结点失败
- return ERROR;
- for(m=0;m<CHUNK_SIZE&&*chars;m++) // 给块结点的数据域赋值
- *(p->ch+m)=*chars++;
- if(k==0) // 第一个链块
- T.head=q=p; // 头指针指向第一个链块
- else
- {
- q->next=p;
- q=p;
- }
- if(!*chars) // 最后一个链块
- {
- T.tail=q;
- q->next=NULL;
- for(;m<CHUNK_SIZE;m++) // 用填补空余的字符填满链表
- *(q->ch+m)=blank;
- }
- }
- return OK;
- }
- Status ToChars(LString T,char* &chars)
- { // 将串T的内容转换为字符串,chars为其头指针。成功返回OK,否则返回ERROR。另加
- Chunk *p=T.head; // p指向第1个块结点
- int i;
- char *q;
- chars=(char*)malloc((T.curlen+1)*sizeof(char));
- if(!chars||!T.curlen) // 生成字符串数组失败或串T长为0
- return ERROR;
- q=chars; // q指向chars的第1个字符
- while(p) // 块链没结束
- {
- for(i=0;i<CHUNK_SIZE;i++)
- if(p->ch[i]!=blank) // 当前字符不是填补空余的字符
- *q++=(p->ch[i]); // 赋给q所指字符空间
- p=p->next;
- }
- chars[T.curlen]=0; // 串结束符
- return OK;
- }
- Status StrCopy(LString &T,LString S)
- { // 初始条件:串S存在
- // 操作结果:由串S复制得串T,去掉填补空余的字符。成功返回OK,否则返回ERROR
- char *c;
- Status i;
- if(!ToChars(S,c)) // c为串S的内容
- return ERROR;
- i=StrAssign(T,c); // 将串S的内容赋给T
- free(c); // 释放c的空间
- return i;
- }
- Status StrEmpty(LString S)
- { // 初始条件:串S存在。操作结果:若S为空串,则返回TRUE,否则返回FALSE
- if(S.curlen) // 非空
- return FALSE;
- else
- return TRUE;
- }
- int StrCompare(LString S,LString T)
- { // 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
- char *s,*t;
- Status i;
- if(!ToChars(S,s)) // s为串S的内容
- return ERROR;
- if(!ToChars(T,t)) // t为串T的内容
- return ERROR;
- i=strcmp(s,t); // 利用C的库函数
- free(s); // 释放s,t的空间
- free(t);
- return i;
- }
- int StrLength(LString S)
- { // 返回S的元素个数,称为串的长度
- return S.curlen;
- }
- void ClearString(LString &S)
- { // 初始条件:串S存在。操作结果:将S清为空串
- Chunk *p,*q;
- p=S.head;
- while(p)
- {
- q=p->next;
- free(p);
- p=q;
- }
- S.head=S.tail=NULL;
- S.curlen=0;
- }
- Status Concat(LString &T,LString S1,LString S2)
- { // 用T返回由S1和S2联接而成的新串(中间可能有填补空余的字符)
- LString a1,a2;
- Status i,j;
- InitString(a1);
- InitString(a2);
- i=StrCopy(a1,S1);
- j=StrCopy(a2,S2);
- if(!i||!j) // 至少有1个串拷贝不成功
- return ERROR;
- T.curlen=S1.curlen+S2.curlen; // 生成串T
- T.head=a1.head;
- a1.tail->next=a2.head; // a1,a2两串首尾相连
- T.tail=a2.tail;
- return OK;
- }
- Status SubString(LString &Sub, LString S,int pos,int len)
- { // 用Sub返回串S的第pos个字符起长度为len的子串。
- // 其中,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1
- char *b,*c;
- Status i;
- if(pos<1||pos>S.curlen||len<0||len>S.curlen-pos+1) // pos或len值不合法
- return ERROR;
- if(!ToChars(S,c)) // c为串S的内容
- return ERROR;
- b=c+pos-1; // b指向串c中串Sub内容的首地址
- b[len]=0; // Sub结束处赋0(字符串结束符)
- i=StrAssign(Sub,b); // 将串b的内容赋给Sub
- free(c);
- return i;
- }
- int Index(LString S,LString T,int pos)
- { // T为非空串。若主串S中第pos个字符之后存在与T相等的子串,
- // 则返回第一个这样的子串在S中的位置,否则返回0
- int i,n,m;
- LString sub;
- if(pos>=1&&pos<=StrLength(S)) // pos满足条件
- {
- n=StrLength(S); // 主串长度
- m=StrLength(T); // 串T长度
- i=pos;
- while(i<=n-m+1)
- {
- SubString(sub,S,i,m); // sub为从S的第i个字符起,长度为m的子串
- if(StrCompare(sub,T)) // sub不等于T
- ++i;
- else
- return i;
- }
- }
- return 0;
- }
- Status StrInsert(LString &S, int pos,LString T)
- { // 1≤pos≤StrLength(S)+1。在串S的第pos个字符之前插入串T
- char *b,*c;
- int i,j;
- Status k;
- if(pos<1||pos>S.curlen+1) // pos的值超出范围
- return ERROR;
- if(!ToChars(S,c)) // c为串S的内容
- return ERROR;
- if(!ToChars(T,b)) // b为串T的内容
- return ERROR;
- j=(int)strlen(c); // j为串S的最初长度
- c=(char*)realloc(c,(j+strlen(b)+1)*sizeof(char)); // 增加c的存储空间
- for(i=j;i>=pos-1;i--)
- c[i+strlen(b)]=c[i]; // 为插入串b腾出空间
- for(i=0;i<(int)strlen(b);i++) // 在串c中插入串b
- c[pos+i-1]=b[i];
- InitString(S); // 释放S的原有存储空间
- k=StrAssign(S,c); // 由c生成新的串S
- free(b);
- free(c);
- return k;
- }
- Status StrDelete(LString &S,int pos,int len)
- { // 从串S中删除第pos个字符起长度为len的子串
- char *c;
- int i;
- Status k;
- if(pos<1||pos>S.curlen-len+1||len<0) // pos,len的值超出范围
- return ERROR;
- if(!ToChars(S,c)) // c为串S的内容
- return ERROR;
- for(i=pos+len-1;i<=(int)strlen(c);i++)
- c[i-len]=c[i]; // c为删除后串S的内容
- InitString(S); // 释放S的原有存储空间
- k=StrAssign(S,c); // 由c生成新的串S
- free(c);
- return k;
- }
- Status Replace(LString &S,LString T,LString V) // 此函数与串的存储结构无关
- { // 初始条件:串S,T和V存在,T是非空串
- // 操作结果:用V替换主串S中出现的所有与T相等的不重叠的子串
- int i=1; // 从串S的第一个字符起查找串T
- if(StrEmpty(T)) // T是空串
- return ERROR;
- do
- {
- i=Index(S,T,i); // 结果i为从上一个i之后找到的子串T的位置
- if(i) // 串S中存在串T
- {
- StrDelete(S,i,StrLength(T)); // 删除该串T
- StrInsert(S,i,V); // 在原串T的位置插入串V
- i+=StrLength(V); // 在插入的串V后面继续查找串T
- }
- }while(i);
- return OK;
- }
- void StrPrint(LString T)
- { // 输出字符串T。另加
- int i=0,j;
- Chunk *h;
- h=T.head;
- while(i<T.curlen)
- {
- for(j=0;j<CHUNK_SIZE;j++)
- if(*(h->ch+j)!=blank) // 不是填补空余的字符
- {
- printf("%c",*(h->ch+j));
- i++;
- }
- h=h->next;
- }
- printf("/n");
- }