C语言堆串操作详解:基于malloc/realloc的动态分配与核心接口
在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实现及内存管理的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









