str1、str2连接,分别用定长存储、堆存储、块链存储实现

22 篇文章 1 订阅


字符串str1、str2连接,分别用定长存储、堆分配存储、块链存储实现,不能直接调用函数库中自带的连接函数。

1 定长存储

#include<iostream>
using namespace std;
#define MAXLEN 255//定义串的最大长度为255,<=255以内的任何串可用
typedef struct {
	char ch[MAXLEN + 1];//存储串的一维数组,ch[0]~ch[255],共256个
	int length;//串的当前长度
}String;
void StrAssign(String* Str, char str[])//生成一个其值等于字符串常量 str 的串 Str
{
	int i = 0;
	while (str[i] != '\0') i++;//计算str的长度
	Str->length = i;
	for (i = 0; i < Str->length; i++) {
		Str->ch[i] = str[i];//从第一个字符开始,着个赋
	}
}
void StrConcat(String str1, String str2, String* str3)//连接字符串1和2,并存在字符串3中
{
	str3->length = str1.length + str2.length;
	int i;
	for (i = 0; i < str1.length; i++) {//当串1的字符全部赋值给串3,退出当前for循环
		str3->ch[i] = str1.ch[i];
	}  //将str1赋值到str
	for (; i < str3->length; i++) {//此for循环的i从串1长度str1.length开始到str3->length结束
		str3->ch[i] = str2.ch[i - str1.length];
	}  //将str2赋值到str
}
void print(String* str)
{
	int i;
	for (i = 0; i < str->length; i++) {
		cout << str->ch[i];
	}
	cout << endl;
}
int main()
{
	char st1[255], st2[255];
	String str1, str2, str3;
	cout << "请输入第一个串" << endl;
	cin >> st1;
	StrAssign(&str1, st1);
	cout << "请输入第二个串" << endl;
	cin >> st2;
	StrAssign(&str2, st2);
	StrConcat(str1, str2, &str3);
	print(&str3);
	return 0;
}

在这里插入图片描述

2 堆分配存储

#include<iostream>    //堆存储
using namespace std;
#define MAXSIZE 100
typedef struct st {
	char* ch;  //串存放的起始地址
	int length;  //串的长度
	int strsize; //分配的存储空间的大小
}String;
String CreateNullString() {    //初始化
	String str;
	str.length = 0;
	str.ch = (char*)malloc(MAXSIZE * sizeof(char));
	str.strsize = MAXSIZE;
	return str;
}
void StrAssign(String* str1, char str[]) {//生成一个其值等于字符串常量 str 的串 str1
	int i = 0;
	while (str[i] != '\0') i++;//计算str的长度
	if (str1->length < i) {
		//增加存储空间,将较长的空间赋值为新的值
		str1->ch = (char*)malloc(sizeof(char));
		str1->strsize = i;
	}
	str1->length = i;
	for (i = 0; i < str1->length; i++) {
		str1->ch[i] = str[i];//从第一个字符开始,着个赋
	}
}
void StrConcat(String* str, String str1, String str2) {
	if (str->strsize < str1.strsize + str2.strsize) {
		str->ch = (char*)realloc(str->ch, (str->length + str1.length) * sizeof(char));
		str->strsize = str1.length + str2.length;
	}
	str->length = str1.length + str2.length;
	int i;
	for (i = 0; i < str1.length; i++) {
		str->ch[i] = str1.ch[i];
	}  //将str1赋值到str
	for (; i < str->length; i++) {
		str->ch[i] = str2.ch[i - str1.length];
	}  //将str2赋值到str
}
void print(String* str) {
	int i;
	for (i = 0; i < str->length; i++) {
		cout << str->ch[i];
	}
	cout << endl;
}
int main()
{
	char st1[255], st2[255];
	String str1, str2, str3;
	str1 = CreateNullString();
	str2 = CreateNullString();
	str3 = CreateNullString();
	cout << "请输入第一个串" << endl;
	cin >> st1;
	StrAssign(&str1, st1);
	cout << "请输入第二个串" << endl;
	cin >> st2;
	StrAssign(&str2, st2);
	StrConcat(&str3, str1, str2);
	print(&str3);
	return 0;
}

在这里插入图片描述

3 块链存储

在这里插入图片描述

思路(1):两个子串先分成块,再连接

//将两个串先分别转换成块存储
//将已经分好的块进行连接

但这样有个问题,第一个串的最后一块可能不满,显然有些不合理,造成了空间浪费

#include <stdio.h>
#include <iostream>
#include <cstring>
#define CHUNKSIZE 4//用户自定义块的大小
using namespace std;
typedef struct Chunk {  //块链存储结构体
	char ch[CHUNKSIZE];
	struct Chunk* next;
}Chunk;
Chunk* initChunk(char[]);//初始化一个串 
void print_Chunk(Chunk* h);//打印Chunk串 
void contract(Chunk* t, Chunk* s);//将串s插入到串t某个字符后 
int main()
{
	Chunk* s, * t;
	char s_str[100];
	char t_str[100];
	cout << "请输入t串:";
	cin >> t_str;
	cout << "请输入s串:";
	cin >> s_str;
	t = initChunk(t_str);//将两个串先分别,转换成块存储
	s = initChunk(s_str);//将两个串先分别,转换成块存储
	cout << "链接后为:" << endl;
	contract(t, s); //将已经存储好的块进行连接
	print_Chunk(t);//打印连接后的块链
	return 0;
}
Chunk* initChunk(char str[])
{
	Chunk* h, * temChunk, * lastChunk;
	h = new Chunk;//为头结点分配内存, 头结点不储存信息 
	lastChunk = h;
	int num = strlen(str) / CHUNKSIZE;//计算出所需块链的个数
	int mod = strlen(str) % CHUNKSIZE;
	if (mod != 0)num++;//如果不是这整数个块,则块数num+1
	int i, j;
	//对每一个块赋值 
	for (i = 0; i < num; i++)
	{
		temChunk = new Chunk;//为块链分配内存 
		j = 0;
		//当字符串还没有结束以及j<CHUNKSIZE的时候,进行赋值 
		while (j < CHUNKSIZE && str[i])
		{
			temChunk->ch[j] = str[i * CHUNKSIZE + j];//将对应字符赋值
			j++;
		}
		// 尾插法
		//将当前已经完成的这个块,连接在上一个块的后面
		lastChunk->next = temChunk;
		lastChunk = temChunk;
	}
	//如果最后一个块没填满,通常用'#'补上
	if (mod != 0)
	{
		int temp = CHUNKSIZE - mod;
		for (size_t q = 0; q < temp; q++)
		{
			lastChunk->ch[mod + q] = '#';//最后一个块没填满,用'#'补上
		}
	}
	lastChunk->next = NULL;
	return h;
}
void print_Chunk(Chunk* h)
{
	Chunk* temChunk;
	temChunk = h->next;
	int i;
	while (temChunk)//打印输出时,按块输出
	{
		for (i = 0; i < CHUNKSIZE; i++)
		{

			if (temChunk->ch[i] == NULL)
			{
				break;
			}
			else
			{
				cout << temChunk->ch[i] ;
			}

		}
		temChunk = temChunk->next;//一个块输出完毕,继续输出下一个块
		cout << " ";//为了使直观的反映内部存储结构,输出时块与块之间,以空格间隔
	}
	cout << endl;
}
void contract(Chunk* t, Chunk* s)
{
	while (t->next)
	{
		t = t->next;
	}
	t->next = s->next;//直接把s连在t之后	 
}

如图,第一个串的最后一块可能不满,显然有些不合理,造成了空间浪费。
为了便于观察,他是4个一块,第一个串最后一块不满的用#补上

//为了使直观的反映内部存储结构,输出时块与块之间,以空格间隔
在这里插入图片描述
第二个串最后一块不满的用#补上
在这里插入图片描述

思路(2)先连接,再分块存储

//先把两个串连接
//然后再按照块链的方式存储

#include <iostream>
#include<string>
#include<cstring>
#define CHUNKSIZE 5 //用户自定义块的大小
using namespace std;

typedef struct Chunk {//块链存储结构体
	char ch[CHUNKSIZE];
	struct Chunk* next;
}Chunk;

char s_s[200];
Chunk* initChunk(char[]);//初始化一个块链 
void print_Chunk(Chunk* h);//打印Chunk块 
void StrConcat(char s1[], char s2[]);
int main()
{
	Chunk* s, * t;
	char s_str[100];
	char t_str[100];
	cout << "请输入t串:";
	cin >> t_str;
	cout << "请输入s串:";
	cin >> s_str;
	StrConcat(t_str, s_str);//先把两个串连接
	t = initChunk(s_s);//然后再按照块链的方式存储
	print_Chunk(t);//打印连接后的块链
	return 0;
}

Chunk* initChunk(char str[])
{
	Chunk* h, * temChunk, * lastChunk;
	h = new Chunk;//为头结点分配内存, 头结点不储存信息 
	lastChunk = h;
	int len = strlen(str);//串的总长度

	int num = strlen(str) / CHUNKSIZE;//计算出所需块链的个数
	int mod = strlen(str) % CHUNKSIZE;
	if (mod != 0) num++;//如果不是这整数个块,则块数num+1

	int i, j;
	//对每一个块链赋值 
	for (i = 0; i < num; i++)//创建num个块,组成一个块链
	{
		temChunk = new Chunk;//为块链分配内存 
		j = 0;

		//创建单个块,当这个块填满或者字符串结束时,退出本次while循环
		//当字符串还没有结束以及j<CHUNKSIZE的时候,进行赋值 
		while (str[i * CHUNKSIZE + j] != '\0' && j < CHUNKSIZE)
		{
			temChunk->ch[j] = str[i * CHUNKSIZE + j];//将对应字符赋值
			j++;
		}
		// 尾插法
		//将当前已经完成的这个块,连接在上一个块的后面
		lastChunk->next = temChunk;
		lastChunk = temChunk;

		//如果最后一个块没填满,通常用'#'补上
		//当字符串已经结束,并且最后一个块没满,则执行if语句
		if ((i * CHUNKSIZE + j) == (len) && (CHUNKSIZE - mod!=0))
		{
			int temp = CHUNKSIZE - mod;
			for (size_t q = 0; q < temp; q++)
			{
				temChunk->ch[j + q] = '#';//最后一个块没填满,用'#'补上
			}
		}
	}
	lastChunk->next = NULL;//块链完成,最后加上NULL结束


	cout << endl << "当前块的大小为:" << CHUNKSIZE << endl;
	cout << "该块链共有" << num << "个块组成" << endl << endl;
	return h;
}


void print_Chunk(Chunk* h)
{
	Chunk* temChunk;
	temChunk = h->next;
	int i;

	//输出连接后的串
	cout << "连接后的串为:";
	for (i = 0; i < strlen(s_s); i++) {
		cout << s_s[i];
	}
	cout << endl;

	//便于观察块链的内部真实存储结构,输出块链的每一个块的内容
	cout << "块链的存储结构为:";
	while (temChunk)
	{
		for (i = 0; i < CHUNKSIZE; i++)
		{
			if (temChunk->ch[i] == NULL)
			{
				break;
			}
			else
			{
				cout << temChunk->ch[i];
			}
		}
		temChunk = temChunk->next;
		cout << " ";//当一个块输出完毕,输出空格,即每个块之间用空格间隔,还是便于观察
	}
	cout << endl;
}

void StrConcat(char s1[], char s2[])
{
	int i = 0;
	for (; i < strlen(s1); i++)
	{
		s_s[i] = s1[i];
	}

	for (; i < strlen(s1) + strlen(s2); i++)
	{
		s_s[i] = s2[i - strlen(s1)];
	}
}

#define CHUNKSIZE 5 //用户自定义块的大小

当CHUNKSIZE= 5时,
第二个块只有3个字符,后面两个空缺部分用#填补

//为了使直观的反映内部存储结构,输出时块与块之间,以空格间隔
在这里插入图片描述
当CHUNKSIZE= 4时,
存储满两个完整的块
在这里插入图片描述

思路(3)在思路(1)上改进,第一个串的最后一块不满,用第二个串前移补上。但程序是实现上较为复杂,感兴趣的自己研究。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

R-G-B

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值