串 讲义实现

字符串全部是从0位置开始的
在这里插入图片描述

空串:长度为0的空串
空白串:长度为1的空白串

在这里插入图片描述

在这里插入图片描述

class SString
{
public:
	char data[MaxSize];
	int length;
private:
	int *next;
public:
	SString();
	~SString();
	void Assgin(char cstr[]);	//赋值
	void Copy(SString t);		//拷贝
	Status Equal(SString t);
	int Length();
	void Display();
	Status Concat(SString s1, SString s2);
	Status Sub(SString &sub, int pos, int len);
	Status Insert(int pos, SString t);
	Status Delete(int pos, int length);
	int Index(int pos, SString t);
	int Index_KMP(int pos, SString t);
private:
	void get_next(SString t, int *next);
	void get_nexttval(SString t, int *nextval);
};

在这里插入图片描述

class HString
{
public:
	char *data; 	//字符串
	int length;
public:
	HString(const char* str ="");
	HString(const HString& str);
	~HString();
	int size();
	HString Sub(int pos, int len);
	HString Insert(int pos, const HString& t);
	HString Delete(int pos, int len);
	int Index(int pos, HString t);
	int Index_KMP(int pos, HString t);
	void get_next(HString T, int *next);
	void get_nextval(HString T, int *nextval);
	HString& operator = (const HString& str);
	HString operator + (const HString& str);
	bool operator == (const HString& str);
	char operator[] (int index);
};

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

T为连接后的字符串,因为是静态分配的空间,所以存在溢出的情况。

  1. s1和s2连接的长度的小于T的maxSize;直接连入即可
  2. s1+s2 > maxSize 但是只有s2部分溢出;
  3. s1 = T = maxSize, s1全部溢出;

串的连接算法

Status SString::Concat(SString S1, SString S2)
{
	if(S1.length + S2.length <= MaxSize)	//对应第一种情况
	{
		for(int i=0; i<S1.length; i++)
			{
				data[i] = S1.data[i];	//将S1的所有元素复制到新的对象的data数组的前i个位置
			}
		for(int i=0; i<S2.length; i++)
		{
			data[S1.length+i] = S2.data[i];	//将S2字符串的所有元素复制到相应的字符串的后面
		}
		length = S1.length + S2.length;	//更新当前对象的length到的值
	}
	else if(S1.length < MaxSize) //此时已经有S1.length + S2.length > MaxSize
	{
		for(int i=0; i<S1.length; i++)
			{
				data[i] = S1.data[i];	//前面的一部分直接赋值为S1的相应的内容
			}
		for(int i=S1.length; i<MaxSize; i++)	//剩下的部分为S2被截取的一部分
		{
			data[i] = S2.data[i-S1.length];	//注意i的起始位置
		}
		length = MaxSize;
	}
	else	//截断(仅取S1)
	{
		for(int i=0; i<S1.length; i++)
		{
			data[i] = S1.data[i];
		}
		length = MaxSize;
	}
	return OK;
}


在这里插入图片描述

Status SString::Sub(SString &sub, int pos, int len)
{
	if(pos<1 || pos>length || len>(length-pos+1) || len<0)
	{
		return ERROR;
	}
	for(int i=0; i<len; i++)
	{
		sub.data[i] = data[pos-1+i];	//data中的第pos的元素数组下标为pos-1(+i表示往后的第i个)
	}
	sub.length = len;
	return OK;
}

在这里插入图片描述

即将子串t插入到串S中的第pos个位置
思路:将pos位置之后的元素后移(从后往前复制),给t腾出位置,然后在将t直接插入即可。

//在当亲串中第pos之前插入串t
Status SString::Insert(int pos, SString t)
{
	if(pos<0 || pos>length)
	{
		return ERROR;	//插入位置不合理
	}
	if(length + t.length > MaxSize)
	{
		return ERROR;	//超过总长度不合法
	}
	else	//插入后的串长<=MaxSize的情况
	{
		for(int i=length; i>=pos; i--)
		{
			data[t.length+i] = data[i];
		}
		for(int i=0; i<t.length; i++)
		{
			data[pos+i] = t.data[i];
		}
		length += t.length;
	}
	return OK;
}

在这里插入图片描述

思路:将pos+len后面的字符赋值到从pos开始的位置即可。

//在串s中删除从序号pos起len个字符
Status SString::Delete(int pos, int len)
{
	if(pos<0 || pos>length-len-1)	//后面的条件表示不能删除对应长度为len的字符串
	{
		return ERROR;
	}
	for(int i=pos+len; i<=length; i++)
	{
		data[i-len] = data[i];
	}
	length -= len;
	return OK;
}

完整源码

#include <iostream>
#include <cstring>
using namespace std;

typedef int Status;
const int MaxSize = 20;
const int ERROR = 0;
const int OK = 1;

class SString
{
public:
	char data[MaxSize];
	int length;
private:
	int *next;
public:
	SString();
	SString(const char *str);
	~SString();
	void Assgin(char cstr[]);	//赋值
	void Copy(SString t);		//拷贝
	Status Equal(SString t);
	int Length();
	void Display();
	Status Concat(SString s1, SString s2);
	Status Sub(SString &sub, int pos, int len);
	Status Insert(int pos, SString t);
	Status Delete(int pos, int length);
	int Index(int pos, SString t);
	int Index_KMP(int pos, SString t);
private:
	void get_next(SString t, int *next);
	void get_nexttval(SString t, int *nextval);
};

class HString
{
public:
	char *data; 	//字符串
	int length;
public:
	HString(const char* str = "");
	HString(const HString& str);
	~HString();
	int size();
	HString Sub(int pos, int len);
	HString Insert(int pos, const HString& t);
	HString Delete(int pos, int len);
	int Index(int pos, HString t);
	int Index_KMP(int pos, HString t);
	void get_next(HString T, int *next);
	void get_nextval(HString T, int *nextval);
	HString& operator = (const HString& str);
	HString operator + (const HString& str);
	bool operator == (const HString& str);
	char operator[] (int index);
};


SString::SString()
{
	length = 0;
}

SString::SString(const char *str)
{
	int i;
	int len = strlen(str);
	for (i = 0; i<len; i++)
	{
		data[i] = *str++;
	}
	data[i] = '\0';
	length = len;
}

SString::~SString()
{
	//delete[] data;
}

void SString::Assgin(char cstr[])
{
	int i;
	for (i = 0; cstr[i] != '\0'; i++)
	{
		data[i] = cstr[i];
		length++;
	}
	data[i] = '\0';
}

void SString::Display()
{
	int i = 0;
	while (data[i] != '\0')
	{
		cout << data[i++];
	}
	cout << endl;
}

Status SString::Concat(SString S1, SString S2)
{
	if (S1.length + S2.length <= MaxSize)	//对应第一种情况
	{
		for (int i = 0; i<S1.length; i++)
		{
			data[i] = S1.data[i];	//将S1的所有元素复制到新的对象的data数组的前i个位置
		}
		for (int i = 0; i<S2.length; i++)
		{
			data[S1.length + i] = S2.data[i];	//将S2字符串的所有元素复制到相应的字符串的后面
		}
		length = S1.length + S2.length;	//更新当前对象的length到的值
		data[length] = '\0';
	}
	else if (S1.length < MaxSize) //此时已经有S1.length + S2.length > MaxSize
	{
		for (int i = 0; i<S1.length; i++)
		{
			data[i] = S1.data[i];	//前面的一部分直接赋值为S1的相应的内容
		}
		for (int i = S1.length; i<MaxSize; i++)	//剩下的部分为S2被截取的一部分
		{
			data[i] = S2.data[i - S1.length];	//注意i的起始位置
		}
		length = MaxSize;
	}
	else	//截断(仅取S1)
	{
		for (int i = 0; i<S1.length; i++)
		{
			data[i] = S1.data[i];
		}
		length = MaxSize;
	}
	return OK;
}

Status SString::Sub(SString &sub, int pos, int len)
{
	if (pos<1 || pos>length || len>(length - pos + 1) || len<0)
	{
		return ERROR;
	}
	for (int i = 0; i<len; i++)
	{
		sub.data[i] = data[pos + i];	//data中的第pos的元素数组下标为pos-1(+i表示往后的第i个)
	}
	sub.length = len;
	return OK;
}

//在当前串中第pos之前插入串t
Status SString::Insert(int pos, SString t)
{
	if (pos<0 || pos>length)
	{
		return ERROR;	//插入位置不合理
	}
	if (length + t.length > MaxSize)
	{
		return ERROR;	//超过总长度不合法
	}
	else	//插入后的串长<=MaxSize的情况
	{
		for (int i = length; i >= pos; i--)
		{
			data[t.length + i] = data[i];
		}
		for (int i = 0; i<t.length; i++)
		{
			data[pos + i] = t.data[i];
		}
		length += t.length;
	}
	return OK;
}

//在串s中删除从序号pos起len个字符
Status SString::Delete(int pos, int len)
{
	if (pos<0 || pos>length - len - 1)	//后面的条件表示不能删除对应长度为len的字符串
	{
		return ERROR;
	}
	for (int i = pos + len; i <= length; i++)
	{
		data[i - len] = data[i];
	}
	length -= len;
	return OK;
}


//子串的定位回溯算法
//匹配成功,函数返回值为和模式t中第一个字符相等的字符在主串s
//中的序号,即有效位移。匹配不成功,函数返回值为0
int SString::Index(int pos, SString t)
{
	int i, j;
	if (t.length == 0 || pos<0)	//模式串的长度为0或者起始位置不符合
	{
		return 0;
	}
	i = pos;
	j = 0;
	while (i<length && j<t.length)		//当两个指针均未到尾部时,循环继续
	{
		if (data[i] == t.data[j])
		{
			i++;	//两个指针同时后移
			j++;
		}
		else
		{
			i = i - j + 1;	//回溯的过程
			j = 0;
		}

	}
	if (j>=t.length)
	{
		return (i - j);	//返回起始位置
	}
	else
	{
		return 0;
	}
}

int main()
{
	char a[] = "abcdefg";
	char b[] = "hijklmn";
	SString s1;
	s1.Assgin(a);
	cout << "S1 = ";
	s1.Display();
	SString s2;
	s2.Assgin(b);
	cout << "S2 = ";
	s2.Display();


	SString s3;
	s3.Concat(s1, s2);
	cout << "S3 = S1 + S2 = ";
	s3.Display();

	SString s4("hij");
	cout << "S4 = ";
	s4.Display();

	cout << "KF算法测试,在S3中查找S4:"<<endl;
	cout << "S4 在 S3 中第一次出现的位置是 " << s3.Index(0, s4)<<endl;

	cout << "Test Sub function~" <<endl;
	SString s5;
	s3.Sub(s5, 5, 3);
	s3.Display();
	s5.Display();

	cout << "Test Delete function~"<<endl;
	s3.Delete(3, 5);
	s3.Display();

	cout << "Test Insert function~" <<endl;
	SString s6("defgh");
	s3.Insert(3, s6);
	s3.Display();
	return 0;
}

}

在这里插入图片描述


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/HdUIprince/article/details/82989791