串的堆分配存储表示的特点是,仍以一组地址连续的存储单元存放串值字符序列,但它们的存储空间是在程序执行过程中动态分配的。使用动态分配函数malloc()和函数free()来管理存储空间的大小。
串的堆分配存储方法具有顺序存储的特点,又弥补了定长存储的大小限制,多以多被采用。
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 typedef int Status; 6 #define OK 1 7 #define ERROR 0 8 #define OVERFLOW -2 9 10 typedef struct{ 11 char *ch; //若是非空串,则按串长度分配存储区域,否则ch为NULL 12 int length; //串的长度 13 }String; 14 15 /*生成一个其值等于等于串常量chars的串T*/ 16 Status StrAssign(String &T, char *chars){ 17 if(T.ch) 18 free(T.ch); //若串存储空间不为NULl 释放原有空间 19 int i = strlen(chars); //获取chars长度 20 if(!i){ 21 T.ch = NULL; //串常量chars长度为0时串为空串长度0存储区间指向NULL 22 T.length = 0; 23 } 24 else{ 25 T.ch = (char *)malloc(i * sizeof(char)); //申请空间 26 if(!T.ch) 27 exit(OVERFLOW); 28 for(int j = 0; j < i; j++) 29 T.ch[j] = chars[j]; //写入chars串 30 T.length = i; 31 } 32 return OK; 33 } 34 35 /*由串S复制得到T*/ 36 Status StrCopy(String &T, String S){ 37 if(T.ch) 38 free(T.ch); 39 T.ch = (char*)malloc(S.length * sizeof(char)); 40 if(!T.ch) 41 exit(OVERFLOW); 42 for(int j = 0; j < S.length; j++) 43 T.ch[j] = S.ch[j]; 44 T.length = S.length; 45 return OK; 46 } 47 48 /*如果串S为空串则返回true否则返回false*/ 49 bool StrEmpty(String S){ 50 if(S.length == 0) 51 return true; 52 else 53 return false; 54 } 55 56 /*若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0*/ 57 int StrCompare(String T, String S){ 58 for(int i = 0; i < S.length && i < T.length; i++) 59 if(S.ch[i] != T.ch[i]) 60 return S.ch[i] - T.ch[i]; 61 return S.length - T.length; 62 } 63 64 /*返回串的长度*/ 65 int StrLength(String S){ 66 return S.length; 67 } 68 69 /*清空串*/ 70 Status ClearString(String &S){ 71 if(S.ch){ 72 free(S.ch); 73 S.ch = NULL; 74 } 75 S.length = 0; 76 return OK; 77 } 78 79 /*用T返回S1和S2两个串的连接串*/ 80 Status Concat(String &T, String S1, String S2){ 81 T.length = S1.length + S2.length; 82 if(T.ch) 83 free(T.ch); 84 T.ch = (char*)malloc(T.length * sizeof(char)); 85 if(!T.ch) 86 exit(OVERFLOW); 87 for(int i=0; i < S1.length; i++) 88 T.ch[i] = S1.ch[i]; 89 for(int i=0; i < S2.length;i++) 90 T.ch[S1.length+i] = S2.ch[i]; 91 return OK; 92 } 93 94 /*用Sub返回串S的第pos位置起的长度len的子串*/ 95 Status SubString(String &Sub, String S, int pos, int len){ 96 if(pos<1 || pos>S.length || len<0 || len>S.length-pos+1) 97 return ERROR; 98 if(Sub.ch) 99 free(Sub.ch); 100 if(!len){ 101 Sub.ch = NULL; 102 Sub.length = 0; 103 } 104 else{ 105 Sub.ch = (char*)malloc(len*sizeof(char)); 106 if(!Sub.ch) 107 exit(OVERFLOW); 108 for(int i = 0; i < len-1; i++) 109 Sub.ch[i] = S.ch[pos-1+i]; 110 Sub.length = len; 111 } 112 return OK; 113 } 114 115 116 Status Index(String S, String T, int pos){ 117 /*Index函数有两种写法,一种是调用串函数实现一个个字符匹配;另一种是模式串匹配法,详细写法与 118 定长表示法的写法基本一样,可以去参考另一篇定长表示串的函数 119 */ 120 return ERROR; 121 } 122 123 /*在串S的第pos个字符之前插入串T*/ 124 Status StrInsert(String S,int pos,String T) 125 { 126 if(pos<1 || pos>S.length+1) 127 return ERROR; 128 if(T.length){ 129 S.ch = (char*)realloc(S.ch,(S.length+T.length)*sizeof(char)); 130 if(!S.ch) 131 exit(OVERFLOW); 132 for(int i = S.length-1; i >= pos-1; --i) 133 S.ch[i+T.length] = S.ch[i]; 134 for(int i = 0; i < T.length; i++) 135 S.ch[pos-1+i] = T.ch[i]; 136 S.length += T.length; 137 } 138 return OK; 139 } 140 141 /* 从串S中删除第pos个字符起长度为len的子串 */ 142 Status StrDelete(String S,int pos,int len) 143 { 144 if(S.length < pos+len-1) 145 exit(ERROR); 146 for(int i = pos-1; i <= S.length-len; i++) 147 S.ch[i] = S.ch[i+len]; 148 S.length -= len; 149 S.ch = (char*)realloc(S.ch,S.length*sizeof(char)); 150 return OK; 151 } 152 /*用V替换主串S中出现的所有与T相等的不重叠的子串 */ 153 Status Replace(String &S,String T,String V) 154 { 155 int i=1; 156 if(StrEmpty(T)) 157 return ERROR; 158 do{ 159 i=Index(S,T,i); 160 if(i) 161 { 162 StrDelete(S,i,StrLength(T)); 163 StrInsert(S,i,V); 164 i += StrLength(V); 165 } 166 }while(i); 167 return OK; 168 }