2016年7月26日14:47:30
为什么需要字符串的堆分配?
因为字符串的顺序存贮结构中,对字符串的操作,在字符串中插入一个子字符串,连接两个字符串以及串的替换操作,度可能会
出现空间的不足,而必须要舍弃部分数据的情况,而数组的空间如果分配的过大,又会浪费内存空间,为了避免顺序存贮结构的
局限性,可以使用动态内存分配的方式来表示串,并实现串的基本操作
什么是堆分配?
通常在函数中定义的变量,都属于局部变量,他们属于静态内存分配,是由程序所在的软件,请求操作系统分配一块空闲的存贮空间
当函数运行完毕后,函数会弹栈,静态分配的存贮空间就会被操作系统释放,程序员无法手动编写代码来分配和释放这些内存空间,
而动态内存分配则不同,动态内存分配可以由程序员手动分配内存空间,是使用堆排序的方式进行分配的,函数运行完毕后,函数以及
它的所有局部变量都会出栈,但是堆分配产生的内存空间则任然存在,这些内存空间必须由程序员手动进行释放.空间可以动态的
缩小与扩充.
realloc函数:指针名 = (数据类型 * )realloc(需要改变内存大小的指针名,新的大小);动态内存调整
使用时必须包含头文件#include<stdlib.h>;
功能:先判断当前指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回.
如果内存空间不够,先按照新指定的大小分配空间,将原来数据从头到尾拷贝到新分配的内存区域,(注意:原来指针是自动释放的)
不需要使用free函数进行释放,同时返回新分配的内存区域的首地址,
返回值:如果分配成功则返回被分配内存空间的首地址,如果分配失败,则返回NULL;
注意:当内存不在使用时,应使用free()函数将内存块进行释放;
//字符串的堆分配表示与实现
typedef struct string
{
char * str;//保存的是堆内存的串的起始地址的指针
int length;//动态数组的长度
}HeapString;
//函数前置声明
void initString(HeapString * pH);//初始化字符串
void strAssign(HeapString * pH,char cstr[]);//给字符串赋值
void traverseStr(HeapString * pH);//将给定的字符串遍历输出
int getLength(HeapString * pH);//获取字符串的长度
void strCopy(HeapString * S,HeapString * T);//字符串的复制
int strInsert(HeapString * pH,HeapString * S);//字符串的插入
//字符串的插入,将S所指向的字符串插入到pH所指向的字符串pos中,成功返回1,失败返回0
int strInsert(HeapString * pH,int pos,HeapString * S)
{
int i;
//判断pos的值是否合法;
if(pos<1||pos>pH->length+1)
{
printf("位置不合适!\n");
return 0;
}
//从新分配内存空间
pH->str = (char *)realloc(pH->str,(pH->length+S->length)*sizeof(char));
if(!pH->str)
{
printf("动态内存分配失败!\n");
exit(-1);
}
//将pos及其以后的所有元素向后移动:方法一
/*for(i = pH->length+S->length-1;i>=pos-1+S->length;i--)
{
//pH->str[pH->length+S->length-1] = pH->str[pH->length-1];
//pH->str[pH->length+S->length-1-1] = pH->str[pH->length-1-1];
pH->str[i] = pH->str[i-S->length];
}*/
//将pos及其以后的所有元素向后移动:方法二
for(i = pH->length-1;i>=pos-1;i--)
{
//pH->str[pH->length-1+S->length] = pH->str[pH->length-1];
//pH->str[pH->length-1+S->length-1] = pH->str[pH->length-1-1];
pH->str[i+S->length] = pH->str[i];
}
//将元素插入到pH所指向的字符串的"空"出来的部分:方法一
for(i = 0;i<S->length;i++)
{
//pH->str[pos-1] = S->str[0];
//pH->str[pos] = S->str[1];
pH->str[i+pos-1]= S->str[i];
}
//将元素插入到pH所指向的字符串的"空"出来的部分:方法二
/*for(i = pos-1;i<pos-1+S->length;i++)
{
//pH->str[pos-1] = S->str[0];
//pH->str[pos] = S->str[1];
pH->str[i] = S->str[i-(pos-1)];
}*/
pH->length = pH->length+ S->length;
return 1;
}
//字符串的复制
void strCopy(HeapString * pH,HeapString * T)
{
int i;
int len = pH->length;
T->str = (char * )malloc(len*sizeof(char));
if(!T->str)
{
printf("动态内存分配失败!\n");
exit(-1);
}
for( i = 0;i<pH->length;i++)
{
T->str[i] = pH->str[i];
}
T->length = pH->length;
return;
}
//获取字符串的长度
int getLength(HeapString * pH)
{
return pH->length;
}
//字符串的遍历
void traverseStr(HeapString * pH)
{
int i;
for(i = 0;i<pH->length;i++)
{
printf("%c",pH->str[i]);
}
printf("\n");
return ;
}
//给指定的字符串赋值
void strAssign(HeapString * pH,char cstr[])
{
int i;
int len;
if(pH->str)
free(pH->str);
for( i = 0;cstr[i]!='\0';i++);
len = i;
if(!cstr)
{
pH->length = 0;
pH->str = '\0';
}
else
{
pH->str = (char * )malloc(len*sizeof(char));
if(!pH->str)
{
printf("动态内存分配失败!\n");
exit(-1);
}
for(i = 0;i<len;i++)
{
pH->str[i] = cstr[i];
}
pH->length = len;
}
return ;
}
//初始化串
void initString(HeapString * pH)
{
pH->str ='\0';
pH->length = 0;
return ;
}
//主函数
int main(void)
{
HeapString pH;
char cstr[MAXISIZE];
initString(&pH);
printf("请输入一个字符串:");
gets(cstr);
strAssign(&pH,cstr);
traverseStr(&pH);
return 1;
}