以一组地址连续的存储单元存放串值字符序列,但它们的存储空间是在程序执行过程中动态分配而得。
下面是基本操作的头文件
#define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define MYOVERFLOW -2 typedef int Status; //-------串的堆分配存储表示--------- typedef struct{ char *ch; //若是非空串,则按串长分配存储区,否则ch为NULL int length; //串长度 }HString; //------基本操作的函数原型说明-------- Status StrAssign(HString &T, char *chars);//生成一个其值等于串常量chars的串T int StrLength(HString S);//返回S的元素个数,称为串的长度 int StrCompare(HString S, HString T);//若S>T,则返回值>0;若S==T,则返回值为0,若S<T,则返回值<0 Status ClearString(HString &S);//将S清为空串,并释放S所占空间 Status Concat(HString &T, HString S1, HString S2);//用串T返回由S1和S2联接而成的新串 Status SubString(HString &Sub,HString S, int pos, int len); //1<=pos<<StrLength(S)且0<=len<=StrLength(S)-pos+1 //返回串S的第pos个字符起长度为len的子串 Status StrCopy(HString &T, HString S);//串S存在,由串S复制得到串T Status StrEmpty(HString S);//串S存在,若S为空串,则返回TRUE,否则返回FALSE int Index(HString S, HString T, int pos); //串S和串T存在,T是非空串,1<=pos<<Strlength(s).若主串S中存在和串T值相同的子串,则返回 //它在主串S中第pos个字符之后第一次出现的位置;否则函数值为0; Status Replace(HString &S, HString T, HString V); //串S,T和V存在,T是非空串 //用V替换主串S中出现的所有与T相等的不重叠的子串 Status StrInsert(HString &S, int pos, HString T); //串S和T存在,1<=pos<<Strlength(S)+1.在串S的第pos个字符之前插入串T Status StrDelete(HString &S, int pos, int len); //串S存在,1<=pos<<Strlength(S)-len+1。从串S中删除第pos个字符起长度为len的子串 Status DestroyString(HString &S); //串S存在,串S被销毁
上述基本操作的实现:
#include"stdafx.h" Status StrAssign(HString &T, char *chars)//生成一个其值等于串常量chars的串T { if (T.length > 0)delete T.ch;//如果T存在值,则删除T以前所占空间 int i = 0; for (char *c = chars; *c; ++c, ++i){}//求chars的长度 if (!i){ T.ch = NULL; T.length = 0; } else{ if (!(T.ch = (char *)malloc((i+1)*sizeof(char))))//为T分配i+1个空间,最后一个空间储存NULL是为了操作方便 exit(MYOVERFLOW); for (int j = 0; j < i; j++)//将chars[]的值传给T T.ch[j] = chars[j]; T.ch[i] = NULL; T.length = i; //T.length=i; } return OK; } int StrLength(HString S)//返回S的元素个数,称为串的长度 { return S.length; } int StrCompare(HString S, HString T)//若S>T,则返回值>0;若S==T,则返回值为0,若S<T,则返回值<0 { for(int i=0;i<S.length&&i<T.length;i++) if (*(S.ch+i) != *(T.ch+i))//如果在未达到其中一个字符串的末端就有不等的,则返回第一个不相等的两字符之差 return *(S.ch) - *(T.ch); return S.length - T.length;//如果全部相等,则返回字符串长度之差 } Status ClearString(HString &S)//将S清为空串,并释放S所占空间 { if (S.length) delete S.ch;//删除S所占空间 S.ch = NULL; S.length = 0; return OK; } Status Concat(HString &T, HString S1, HString S2)//用串T返回由S1和S2联接而成的新串 { if (T.length > 0)delete T.ch; T.ch = (char *)malloc((S1.length + S2.length+1)*sizeof(char));//为T分配空间,最后一个空间储存NULL是为了操作方便 if (!T.ch)exit(MYOVERFLOW); int i = 0; for (; i < S1.length; i++)//将S1的值传给T T.ch[i] = S1.ch[i]; for (int j = 0; i < S1.length + S2.length; i++, j++)//将S2的值传给T T.ch[i] = S2.ch[j]; T.ch[i] = NULL; T.length = S1.length + S2.length; return OK; } Status SubString(HString &sub, HString S, int pos, int len) //1<=pos<<StrLength(S)且0<=len<=StrLength(S)-pos+1 //返回串S的第pos个字符起长度为len的子串 { if (sub.length > 0)delete sub.ch; if (len == 0){ sub.ch = NULL; sub.length = len; } else{ if (pos >= 1 && pos <= S.length&&len > 0 && len <= S.length - pos + 1) { sub.ch = (char *)malloc(len+1*sizeof(char));//为子串分配空间 if (!sub.ch)exit(MYOVERFLOW); for (int i = 0; i < len; i++, pos++)//将相对应的字符传给子串 sub.ch[i] = S.ch[pos-1]; sub.ch[len] = NULL; sub.length = len; return OK; } } return ERROR; } Status StrCopy(HString &T, HString S)//串S存在,由串S复制得到串T { if (T.length > 0)delete T.ch; if (S.length < 0)return ERROR; else{ if (S.length == 0){ T.ch = NULL; T.length = 0; return OK; } T.ch = (char *)malloc((S.length + 1)*sizeof(char));//为T分配空间 for (int i = 0; i <= S.length; i++)//将S的值传给T T.ch[i] = S.ch[i]; T.length = S.length; return OK; } } Status StrEmpty(HString S)//串S存在,若S为空串,则返回TRUE,否则返回FALSE { if (S.length == 0)return FALSE; else return TRUE; } int Index(HString S, HString T, int pos) //串S和串T存在,T是非空串,1<=pos<<Strlength(s).若主串S中存在和串T值相同的子串,则返回 //它在主串S中第pos个字符之后第一次出现的位置;否则函数值为0; { if (T.length == 0)return 0; pos++; for (; pos + T.length-1 <= S.length; pos++) { HString sub; SubString(sub, S, pos, T.length);//求长度相等的子串 if (StrCompare(T, sub) == 0)return pos;//如果该子串与T相等,则返回第一次出现的位置 } return 0; } Status Replace(HString &S, HString T, HString V) //串S,T和V存在,T是非空串 //用V替换主串S中出现的所有与T相等的不重叠的子串 { if (T.length <= 0)return ERROR; for (int i = 0; i <= S.length - T.length; ){ int j = 0; if (j = Index(S, T, i)){//如果S中存在于T相等的子串,则用V替换T HString sub1,sub2,temp; SubString(sub1, S, 1, j - 1);//求T之前的子串 Concat(temp, sub1, V); //将前子串与V相连保存在temp中 if (SubString(sub2, S, j + T.length, S.length - T.length - j + 1))//求T之后的子串,如果T恰好在S的末尾,则不执行下面的操作 { Concat(S, temp, sub2);//将temp和后子串相连 i = j + V.length - 1;//因为不重叠,所以要将i的值移到j+V.length-1的位置上 } else { //如果没有后子串则直接将temp拷贝给S StrCopy(S, temp); break; } } else break; } return OK; } Status StrInsert(HString &S, int pos, HString T) //串S和T存在,1<=pos<=Strlength(S)+1.在串S的第pos个字符之前插入串T { if (S.length >= 0 && T.length >= 0 && 1 <= pos&&pos <= S.length + 1){ if (pos == S.length + 1){//如果是在S之后插入T HString temp; Concat(temp, S, T);//将S和T连接 StrCopy(S, temp);//将S和T连接的值传给S return OK; } HString sub1, sub2,temp;//如果是在S中间插入T SubString(sub1, S, 1, pos - 1);//求前子串 SubString(sub2, S, pos, S.length - pos + 1);//求后子串 Concat(temp, sub1, T);//前子串与T相连保存在temp中 Concat(S, temp, sub2);//后子串与temp相连传给S return OK; } else return ERROR; } Status StrDelete(HString &S, int pos, int len) //串S存在,1<=pos<<Strlength(S)-len+1。从串S中删除第pos个字符起长度为len的子串 { if (1 <= pos&&pos <= S.length - len + 1){ HString str1, str2; SubString(str1, S, 1, pos - 1);//求删除子串前的子串 SubString(str2, S, pos + len, S.length - pos - len + 1);//求删除子串后的子串 Concat(S, str1, str2);//将前子串和后子串相连 return OK; } else return ERROR; } Status DestroyString(HString &S) //串S存在,串S被销毁 { if (S.length>0){ delete S.ch; S.length = 0; return OK; } else return ERROR; }
主函数:
// HString.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { HString str1, str2,str3; char ch[] = "lidanldan"; StrAssign(str1, ch); char ch1[] = "dan"; StrAssign(str2, ch1); char ch2[] = "dd"; StrAssign(str3, ch2); Replace(str1, str2, str3);//验证替换 cout << str1.ch << endl; StrInsert(str2, 2, str3);//验证插入 cout << str2.ch << endl; StrDelete(str2, 2, 2); //验证删除 cout << str2.ch << endl; return 0; }
结果:
这是延续了C语言的风格,在字符串末尾加上一个结束字符。。C语言用'\0',本人用NULL。。其实在C++的最新标准中C++11,是不推荐这种风格的。而且不推荐用字符数组来表示字符串,而是用string