数据结构---串的基本操作---c实现

8 篇文章 0 订阅
4 篇文章 0 订阅

描述

本次讲的是动态数组构成的字符串的基本操作的实现,线性表离不开增删查改,以下是将要实现的功能。

具体实现的是串的六个功能:

1. 初始化
2. 插入字符串
3. 删除某个子串
4. 取子串
5. 消除字符串
6. 输出字符串

0.需要的头文件和定义的类型和结构体变量的实现

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

typedef char* Char; 	//定义字符指针方便打代码---个人习惯。。。

typedef struct string {
	Char str;			//定义字符指针
	int length;			//当前长度
	int maxLength;		//最大长度
}string, *String;		

1.初始化

String createString(Char s, int maxLength) {
	if (strlen(s) >= maxLength) {
		printf("最大长度不可以比当前长度短");
		return NULL;
	}
	String newStr = (String)malloc(sizeof(string));
	newStr->length = strlen(s);
	newStr->maxLength = maxLength;
	newStr->str = (Char)malloc(sizeof(char) * maxLength);
	for (int i = 0; i < strlen(s); i++) {
		newStr->str[i] = s[i];
	}
	newStr->str[newStr->length] = '\0';
	return newStr;
}

2. 插入字符串

int Insert(String Str, int index, string insert_Str) {
	int i;
	if (index < 0 ) {
		printf("Insert 函数的参数错误");
		return 0;
	}
	if (Str->maxLength <= Str->length + insert_Str.length) {
		Str->maxLength = Str->length + insert_Str.length +1;	//保证最后一位是\0
		realloc(Str->str, sizeof(char) * Str->maxLength);
	}

	for (i = Str->length - 1; i >= index; i--){
		Str->str[i + insert_Str.length] = Str->str[i];	//正序操作可能重复替换同一个而把后面的替换了,所以要逆序
	}													//就和排队倒退一个道理,最后一个人退了前面的才可以继续后退
	for (i = 0; i < insert_Str.length; i++) {
		Str->str[i + index] = insert_Str.str[i];
	}
	Str->length += insert_Str.length;
	Str->str[Str->length] = '\0';
	return 1;
}

3. 删除某个子串

int Delete(String Str ,int index, int len) {		
	int i;
	if (index <0 || len <= 0 || index + len > Str->length) {
		printf("Detele 函数的参数错误");
		return 0;
	}
	for (i = index; i < index + len; i++) {
		Str->str[i] = Str->str[i + len];
	}
	Str->length -= len;
	Str->str[Str->length] = '\0';	//这步很重要
	return 1;
}

4. 取子串

String subString(String Str,int index, int len) {
	int i;
	String sonStr;
	if (index <0 || len <= 0 || index + len > Str->length){
		printf("subString 函数的参数有误");
		return NULL;
	}
	Char sonstr = (Char)malloc((len + 1) * sizeof(char));
	for (int i = 0; i < len; i++) {
		sonstr[i] = Str->str[index + i];
	}
	sonstr[len] = '\0';
	sonStr = createString(sonstr, len + 1);
	return sonStr;
}

5. 消除字符串

void freeStr(String Str) {
	free(Str->str);
	free(Str);
}

6. 输出字符串

void tostring(String Str) {							
	printf("字符串的最大长度是:%d\n", Str->maxLength);
	printf("字符串的当前长度是:%d\n", Str->length);
	printf("字符串为 %s\n", Str->str);
}

实现效果

在这里插入图片描述

实现效果全部代码

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

typedef char* Char;

typedef struct string {
	Char str;
	int length;
	int maxLength;
}string, *String;

String createString(Char s, int maxLength) {		//初始化函数
	if (strlen(s) >= maxLength) {
		printf("最大长度不可以比当前长度短");
		return NULL;
	}
	String newStr = (String)malloc(sizeof(string));
	newStr->length = strlen(s);
	newStr->maxLength = maxLength;
	newStr->str = (Char)malloc(sizeof(char) * maxLength);
	for (int i = 0; i < strlen(s); i++) {
		newStr->str[i] = s[i];
	}
	newStr->str[newStr->length] = '\0';
	return newStr;
}

void tostring(String Str) {							//输出函数
	printf("字符串的最大长度是:%d\n", Str->maxLength);
	printf("字符串的当前长度是:%d\n", Str->length);
	printf("字符串为 %s\n", Str->str);
}

int Insert(String Str, int index, string insert_Str) {	//插入函数
	int i;
	if (index < 0) {
		printf("Insert 函数的参数错误");
		return 0;
	}
	if (Str->maxLength <= Str->length + insert_Str.length) {
		Str->maxLength = Str->length + insert_Str.length +1;
		realloc(Str->str, sizeof(char) * Str->maxLength);
	}

	for (i = Str->length - 1; i >= index; i--){
		Str->str[i + insert_Str.length] = Str->str[i];	//正序操作可能重复替换同一个而把后面的替换了,所以要逆序
	}													//就和排队倒退一个道理,最后一个人退了前面的才可以继续后退
	for (i = 0; i < insert_Str.length; i++) {
		Str->str[i + index] = insert_Str.str[i];
	}
	Str->length += insert_Str.length;
	Str->str[Str->length] = '\0';
	return 1;
}

int Delete(String Str ,int index, int len) {		//删除函数
	int i;
	if (index <0 || len <= 0 || index + len > Str->length) {
		printf("Detele 函数的参数错误");
		return 0;
	}
	for (i = index; i < index + len; i++) {
		Str->str[i] = Str->str[i + len];
	}
	Str->length -= len;
	Str->str[Str->length] = '\0';
	return 1;
}

String subString(String Str,int index, int len) {		//取子串函数
	int i;
	String sonStr;
	if (index <0 || len <= 0 || index + len > Str->length){
		printf("subString 函数的参数有误");
		return NULL;
	}
	Char sonstr = (Char)malloc((len + 1) * sizeof(char));
	for (int i = 0; i < len; i++) {
		sonstr[i] = Str->str[index + i];
	}
	sonstr[len] = '\0';
	sonStr = createString(sonstr, len + 1);
	return sonStr;
}

void freeStr(String Str) {				//消除函数	
	free(Str->str);
	free(Str);
}

void main() {
	String sonStr;
	String Str = createString("123", 5);
	String insertStr = createString("45", 3);
	tostring(Str);
	printf("\n在下标1处插入字符串 45 :\n");
	if (Insert(Str, 1, *insertStr))tostring(Str);
	printf("\n在下标1处删除字符串长度为2 :\n");
	if (Delete(Str, 1, 2)) tostring(Str);
	printf("\n截取从下标1处开始字符串长度为2的子串 :\n");
	sonStr = subString(Str, 1, 2);
	tostring(sonStr);
	printf("消除字符串 :");
	freeStr(Str);
	freeStr(sonStr);
	printf("成功消除");
}

串我以前都以为是用链表实现的,但是因为用链表会造成空间浪费
(指针占用空间)sizeof(unsigned long int) + sizeof(char) = sizeof(char) * 5
会造成80%的空间的浪费,所以用动态数组。这种做法真是开了眼界。
实现主要用的是 realloc 函数。

晚一点会更新模式匹配的两种算法,主讲KMP。可能是明天,也可能是后天,这两天课比较多。

如果这篇文章有什么不足,可以评论,我一定会及时更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值