C语言堆串操作详解:基于malloc/realloc的动态分配与核心接口

雨后青山
雨后青山
发布时间:2026-10-16 | 4人浏览过
原创

在C语言中,堆串利用 malloc 和 realloc 实现动态存储,解决了定长顺序串的截断风险。本文将详细拆解基于堆串的初始化、赋值、连接、插入及删除操作的代码实现与运行结果。

一、堆串概念与内存管理机制

堆串(Heap String)与定长顺序串的存储结构类似,同样使用一组地址连续的存储单元来存放字符序列。其核心差异在于空间分配方式:堆串的存储空间是通过动态分配获得的。只要内存分配成功,在进行串的插入或连接操作时,就不再受限于初始定义的长度,从而有效避免串过长导致的截断情况。

C语言主要通过以下三个标准库函数对堆串进行动态存储控制:

  • malloc():分配指定大小的内存块。
  • realloc():调整已分配内存块的大小。
  • free():释放不再使用的内存。

二、堆串基本操作详解

以下为堆串的具体实现代码。代码采用 HString 结构体,其中指针 ch 指向动态分配的字符数组起始地址(非空),len 记录当前长度。注意:本实现中下标从1开始作为有效数据索引,0号单元通常预留。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define false 0
#define true 1
typedef struct {
	char *ch;    // 字符数组,若是非空则指向起始地址,若为空则NULL 
	int len;   // 长度 
}HString;
// 初始化
int HInit(HString *s){
	s->ch=NULL;
	s->len=0;
} 
// 串赋值
int HStrAssign(HString *s,const char *chars){
	int i=0;
	while(chars[i]!='\0'){    // 确定串长 
		i++;
	}
	s->len=i;
	if(s->ch!=NULL){
		free(s->ch); // 修正:原代码 free(s) 为错误用法,需释放内部指针 
	}else{
		s->ch=(char *)malloc((s->len+1)*sizeof(char)); // 0号单元不用
		if(s->ch==NULL){ // 修正:原代码判断 s==NULL 应判断返回值 
			printf("空间申请失败!");
			return false;
		} 
	for( i=1;i<=s->len;i++){   // 依次赋值 
		s->ch[i]=chars[i-1];
	}
	}
	return true;
}
// 串遍历
int HSbianli(HString *s){
	if(s->len==0){
		printf("串空!");
		return false; 
	}else{
		int i;
		for(i=1;i<=s->len;i++){
			printf("%c",s->ch[i]);
		}
		return true;
	}
} 
// 串插入
int HStrInsert(HString *s,int pos,const HString t){
	if(pos<1||pos>s->len+1){ // 允许插入到末尾后一位 
		printf("位置不合法!");
		return false;
	}
	char *temp;
	temp=(char *)malloc((s->len+t.len+1) *sizeof(char));
	int i;
	for(i=1;i<pos;i++){    // 将s串pos之前(不含pos)的字符赋给temp 
		temp[i]=s->ch[i];
	}
	for(i=pos;i<pos+t.len;i++){   // 将t串的元素赋给新空间 
		temp[i]=t.ch[i-pos+1];
	}
	for(i=pos;i<=s->len;i++){   // 将s串剩余部分移到后面 
		temp[i+t.len]=s->ch[i];
	}
	free(s->ch);
	s->ch=temp;
	s->len=s->len+t.len;
	return true; 
} 
// 串删除
int HStrDelete(HString *s,int pos,int len){
	if(s->len==0){
		printf("串空!");
		return false;
	}else if(len>s->len-pos+1 || len<0){ // 修正非法参数判断 
		printf("非法位置或删除长度!");
		return false;
	}else if(len == 0){
		return true;
	}else{
		int j;
		for(j=pos+len;j<=s->len;j++){   // 跨度为len的依次前移覆盖 
			s->ch[j-len]=s->ch[j];
		}
		s->len=s->len-len;
		// 注意:严格来说应调用realloc缩小空间以释放内存,此处简化处理
		return true;
	}
} 
// 串连接
 int HStrCon(HString *s,const HString t){
 	if(s->len==0 && t.len==0){ // 两串皆空无需操作
		return true;
	}
 	char *new_ch=(char *)realloc(s->ch,(s->len+t.len+1) *sizeof(char));
 	if(new_ch==NULL){ // 修正:realloc返回值校验
 		printf("空间申请失败!");
 		return false;
	 }
	 s->ch=new_ch;
	if(t.len>0){
		for(int i=1;i<=t.len;i++){
			s->ch[i+s->len]=t.ch[i];
		}
	}
	s->len=s->len+t.len;
	return true;
 }
 // 求字串并打印
 int HStrchild(HString *s,int pos,int len){
 	if(s->len==0){
 		printf("串空!");
 		return false;
	 }else{
	 	int i;
		for(i=pos;i<pos+len;i++){
	 		printf("%c",s->ch[i]);
		 }
		 return true;
	 }
 }
 
int main(){
	HString s,s1;
	HInit(&s);
	HInit(&s1);
	char a[]="aaaaa";
	char b[]="bbb";
	HStrAssign(&s,a);
	HStrAssign(&s1,b);
	printf("-----将aaaaa赋值给s,bbb赋值给s1-----\n");
	printf("此时串s为:"); 
	HSbianli(&s);
	printf("\n此时串s1为:"); 
	HSbianli(&s1);
	printf("\n将s1连接到s为:"); 
	HStrCon(&s,s1);
    HSbianli(&s); 
	printf("\n将串s1插入到s串的第二个位置:");
	HStrInsert(&s,2,s1);
	HSbianli(&s);
	printf("\n再将插入的s1串删除(从第2位删3个):");
	HStrDelete(&s,2,3);
	HSbianli(&s);
	printf("\ns1在第二个元素长度为2的子串为:");
	HStrchild(&s,2,2);
	return 0;
}

三、运行验证

编译并执行上述代码后,控制台将输出按步骤处理的字符串变化。程序依次完成了初始化赋值、尾部连接、中间插入以及随后的删除操作,最终打印出目标子串。整个过程验证了堆串动态调整长度的可行性。

总结

以上就是C语言的堆串操作详解的详细内容,更多关于C语言动态字符串处理、HString实现及内存管理的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表