前言
堆分配顺序串实际上就是动态分配内存的顺序存储结构。它与定长顺序串的区别是:它的串长度可以任意变换,并且不需要预先分配内存。
我们这次额外使用一个变量来保存串的长度,使用char *类型来保存串的实际内容,因此设计出来一个结构体
typedef struct HString{
//空间
char *ch;
//长度
int length;
}HString;
堆分配顺序串的初始化
堆分配顺序串的初始化包括两个部分,第一是把空间的指针初始化为空,第二是把串长初始化为0。
void InitString(HString *s){
//初始化指针为空
s->ch = NULL;
//长度为0
s->length = 0;
}
堆分配顺序串的赋值
在给堆分配顺序串赋值时,首先需要得到要赋值的串的长度,然后去申请对应长度的空间。假设这个串是已经赋过值的,就需要把旧空间释放掉,换成新的空间。因为这个步骤在多个方法中都存在,我们可以额外写一个GetNewSpace方法专门进行如上操作。
void GetNewSpace(HString *s,int len){
//判断原来的空间是否开辟过
if (s->ch != NULL) {
//先释放掉原来的空间
free(s->ch);
}
//新开辟一个空间
s->ch = (char*)malloc(sizeof(char)*len);
assert(s->ch != NULL);
}
这样在赋值时,直接调用方法获得新空间,然后依次赋值即可。
//赋值
void StrAssign(HString *s,char *str){
//获取要赋值的串的长度
int len = (int)strlen(str);
GetNewSpace(s, len);
//赋值
for (int i = 0; i < len; i ++) {
s->ch[i] = str[i];
}
//长度
s->length = len;
}
堆分配顺序串的连接
假设要连接串s1和串s2,并用串t来保存,因为是动态分配的空间,所以不需要考虑能否存得下的问题。只需要让t申请长度为 s1_len + s2_len 的空间,然后直接依次赋值即可。
//链接
void StrConcar(HString *t,HString *s1,HString *s2){
int len1 = StrLength(s1);
int len2 = StrLength(s2);
GetNewSpace(t, len1+len2);
//先拷贝s1
for(int i = 0; i < len1; i ++){
t->ch[i] = s1->ch[i];
}
for (int j = 0; j < len2; j ++) {
t->ch[len1 + j] = s2->ch[j];
}
t->length = len1+len2;
}
堆分配顺序串的插入
假设有串s,需要在pos位置上插入一个子串t,因为是对原有字符串进行的变化,所以不需要调用GetNewSpace方法,而是使用realloc方法,在原有的空间基础上,去重新开辟一个 s_len + t_len 的空间。
void StrInsert(HString *s,int pos,HString *t){
if (pos<0 || pos>s->length) {
printf("要插入的位置非法\n");
return;
}
//需要增大空间
char *ch = (char*