串的堆分配存儲表示的特點是,仍以一組地址連續的存儲單元存放串值字符序列,但它們的存儲空間是在程序執行過程中動態分配的。使用動態分配函數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 }
