第四章(2)串的堆分配的所有操作

本文介绍了一种使用堆分配存储实现串的各种基本操作的方法,包括初始化、生成、比较、连接、子串提取等,并提供了详细的C语言实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第四章(2)串的堆分配的所有操作

利用堆来存储顺序表:


#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//--------ADT String 的表示与实现-------
//1、初始化字符串
//Status InitString(HString *T) 

//2、生成一个其值等于串常量 chars 的串 T
//Status StrAssign(HString &T, char *chars);

//3、返回 S 的元素个数,成为串的长度
//int StrLength(HString S);

//4、若 S>T ,则返回值 >0 ,若S=T,则返回值 =0,若 S<T ,则返回值 <0.
//int StrCompare(HString S,HString T);

//5、将 S 清空为空串,并释放 S 所占空间
//Status ClearString(HString &S);

//6、用 T 返回由 S1 和 S2 链接而成的新串
//Status Concat(HString &T , HString S1, HString S2 );

//7、1<=pos<=StrLength(S) 且 0<=len<=StrLength(S)-pos + 1,返回串 S 的第pos 个字符起长度为 len 的子串
//HString SubString(HString S,int pos,int len);

//8、打印字符串
//Status StrPrint(HString T)

//9、字符串判空
//Status StrEmpty(HString T)

//10、删除字符串中某个位置固定长度的子串,pos是字符串中的位置,删除包括pos的len长
//Status StrDelete(HString *T, int pos, int len)

//11、pos是字符串中的位置,插入时原来的元素(包括pos位)后移
//Status StrInsert(HString *S, int pos, HString T);

//12、在字符串S中索引位置pos之后的子串t
//Status Index(HString S, HString T, int pos);

//13、将字符串T中等于S1的子串替换成为S2
//Status Replace(HString *T, HString S1, HString S2)//宏定义


#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -2
#define STR_INIT_SIZE 100
#define STRINCREMENT 10

typedef int Status;

//-----串的堆分配存储表示-------
typedef struct{
	char *ch;           //若是非空串,则按串长分配存储区,否则 ch 为 NULL
	int length;         //串长度
}HString;


//------基本操作的算法描述-------

//1、初始化字符串
Status InitString(HString *T){
	T->ch=NULL;           //指针指向NULL,长度为0即可
	T->length=0;          //p.s.申请内存空间的过程在赋值中完成
	return OK;
}

//2、生成一个其值等于串常量 chars 的串 T
Status StrAssign(HString *T, char *chars){
	int i,len=strlen(chars);
	char *c;
	if(T->ch)  free(T->ch);    //释放T原有空间
	for(i=0,c=chars ; *c ; ++i,++c );     //求chars的长度i
	if(!i){
		T->ch=NULL;
		T->length=0;
		return ERROR;
	}
	/*  也可以这样利用前面计算出来的 len 来计算
	if (!len)
	{
		T->ch = NULL;
        T->length = 0;
        return ERROR;
	}	*/
	else{
		T->ch=(char *)malloc(i * sizeof(char));
		if(!T->ch)
			exit(OVERFLOW);
		for(i=0;i<len;++i){
			T->ch[i]=chars[i];		//	printf("%c",T.ch[i]);   
		}
			T->length=len;
	}
	return OK;
}

//3、返回 S 的元素个数,成为串的长度
int StrLength(HString S){
	return S.length;
}

//4、若 S>T ,则返回值 >0 ,若S=T,则返回值 =0,若 S<T ,则返回值 <0.
int StrCompare(HString S,HString T){
	int i;
	for(i=0;i<S.length && i<T.length ;i++)
		if(S.ch[i]!=T.ch[i]) 
			return (S.ch[i]-T.ch[i]);
	
	return (S.length-T.length);
}

//5、将 S 清空为空串,并释放 S 所占空间
Status ClearString(HString &S){
	if(S.ch)
	{
		free(S.ch);
		S.ch=NULL;
	}
	S.length=0;
	return OK;
}

//6、用 T 返回由 S1 和 S2 链接而成的新串
Status Concat(HString &T , HString S1, HString S2 ){
	int i;
	if(T.ch) free(T.ch);       //释放旧的空间
	if(!(T.ch=(char *)malloc((S1.length+S2.length)*sizeof(char))))
		exit(OVERFLOW);
	for(i=0;i<S1.length;i++)
		T.ch[i]=S1.ch[i];
	for(i=0;i<S2.length;i++)
		T.ch[S1.length+i]=S2.ch[i];
	T.length=S1.length+S2.length;
	return OK;
}

//7、1<=pos<=StrLength(S) 且 0<=len<=StrLength(S)-pos + 1,返回串 S 的第pos 个字符起长度为 len 的子串
Status SubString(HString &Sub,HString S,int pos,int len){
	int i;
	if(pos<1 || pos>S.length || len<0 || len>S.length-pos+1)
		return ERROR;
	if(Sub.ch)   free(Sub.ch);     //释放旧空间
	if(!len) { Sub.ch=NULL; Sub.length=0; }   //孔子串的时候
	else{
		Sub.ch=(char *)malloc(len * sizeof(char));
		for(i=0;i<len;i++)
			Sub.ch[i]=S.ch[pos+i-1];
		Sub.length=len;
	}
	return OK;
}

//8、打印字符串 ,通过长度判断打印的字符数
void StrPrint(HString T){
	int i;
	for(i=0;i<T.length;i++)
		printf("%c",T.ch[i]);
	printf("\n");
//	return OK;
}

//9、字符串判空
Status StrEmpty(HString T){
	if(T.length==0)
		return TRUE;
	else
		return FALSE;
}

//10、删除字符串中某个位置固定长度的子串,pos是字符串中的位置,删除包括pos的len长
Status StrDelete(HString *T, int pos, int len){
	int i;
	if(pos>T->length)
		return ERROR;
	else if(pos+len>T->length)
		len=T->length-pos+1;
	for(i=pos-1;i<T->length+len;i++)
		T->ch[i]=T->ch[i+len];
	T->length-=len;
	T->ch=(char *)realloc(T->ch,T->length*sizeof(char));
	if(!T->ch)
		exit(OVERFLOW);
	return OK;
}

//11、pos是字符串中的位置,插入时原来的元素(包括pos位)后移
Status StrInsert(HString *S, int pos, HString T){
	int i,len;
	--pos;
	len=StrLength(T);
	S->ch= (char *)realloc(S->ch,(S->length+len)*sizeof(char));
	if(!S->ch) exit(OVERFLOW);
	if(pos>S->length)
		pos=S->length;
	for(i=S->length-1;i>pos-1;i--)   //将pos位之后的向后移
		S->ch[i+len]=S->ch[i];
	for(i=0;i<len;i++)
		S->ch[i+pos]=T.ch[i];
	S->length+=len;
	return OK;
}

//12、在字符串S中索引位置pos之后的子串T
Status Index(HString S, HString T, int pos){
	if(StrEmpty(T))
		return ERROR;
	int i=pos-1,j=0;
	while(i < S.length && j<T.length){
		if( S.ch[i]==T.ch[j] ){
			i++;   j++;
		}//if
		else{
			i=i-j+1;      //重新返回,然后下一个
			j=0;
		}
	}
	if(j>=T.length)
		return i-j+1;   //返回找到之后的起始位置
	else 
		return 0;
}

//13、将字符串T中等于S1的子串替换成为S2
Status Replace(HString *T, HString S1, HString S2){
	//循环索引子串S1在字符串T中的位置(每次的位置从上一次位置后开始查找)
    //从查找到的位置-1开始替换
    //p.s.初始状态下S1为非空串
	int pos=0;
	if(StrEmpty(S1))
		return ERROR;
	do{
		pos=Index(*T,S1,pos); 
		if(pos){
			StrDelete(T,pos,StrLength(S1));
			StrInsert(T,pos,S2);
		}//if
	}while(pos);
	return OK;
}





//---------主函数----------
void main(){
	HString t,s1,s2;
	char *p1="hello xxxa",*p2="hello xxxb";
	char *p="hello world !";
	printf("String *p is: %s\n",p);
	InitString(&t);   //初始化

	//----------判断是否为空
	printf("t is empty and not?");
	if(StrEmpty(t)==1)
		printf("  YES!\n");
	else
		printf("  NO!\n");

	StrAssign(&t,p);
	printf("String t is: ");

	//----------输出其 t 被赋值的数。
	StrPrint(t);   
	printf("\n");
	
	//----------输出 t 的长度
	printf("the t String Length is : %d \n",StrLength(t));

	//----------比较两个字符串的大小
	InitString(&s1);   //初始化
	InitString(&s2);   //初始化
	StrAssign(&s1,p1);
	StrAssign(&s2,p2);
	
	printf("end of the A compare B is: %d \n",StrCompare(s1,s2));  
	printf("\n");
	


	//---------共同使用的
	HString c1,c2,c3;
	char *b3="abcdefg",*b1="efg",*b2="hello";
	InitString(&c1);   //初始化
	InitString(&c2);   //初始化
	InitString(&c3);   //初始化
	StrAssign(&c1,b1);
	StrAssign(&c2,b2);
	StrAssign(&c3,b3);
	//----------index 的使用
	//在字符串S中索引位置pos之后的子串T
    printf("c1在c3的位置是: %d \n",Index(c3,c1,0));

	//----------Replace 的使用
	//将字符串T中等于S1的子串替换成为S2
	printf("替换之前: ");
	StrPrint(c3);
    Replace(&c3,c1,c2);
	printf("替换之后: ");
	StrPrint(c3);
	printf("\n");




	//----------连接两个字符串
	HString T;
	InitString(&T);   //初始化
	Concat(T , s1, s2 );
	StrPrint(T);

	//删除包括pos的len长
	printf("After String Delete: \n");
	StrDelete(&T, 2, 3);
	StrPrint(T);
	printf("\n");

	//----------返回串 S 的第pos 个字符起长度为 len 的子串
	HString Sub;
	InitString(&Sub);   //初始化
	SubString(Sub, T,4,5);
	StrPrint(Sub);

	//---------在pos 位上插入元素
	printf("print the s1 and s2: ");
	StrPrint(s2);
	StrPrint(s2);   printf("\n");
	StrInsert(&s1, 4 , s2);       //将 s2 插入到 s1 的第四个
	printf("print the insert s1: ");
	StrPrint(s1);    
	printf("\n");

	//----------清空字符串
	ClearString(Sub);
	printf("Sub is empty and not?");
	if(StrEmpty(Sub)==1)
		printf("  YES!\n");
	else
		printf("  NO!\n");



}

--------------------------------------------------------------------------------------------------------------------------------如有补充,可以留言:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值