字符串全部是从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为连接后的字符串,因为是静态分配的空间,所以存在溢出的情况。
- s1和s2连接的长度的小于T的maxSize;直接连入即可
- s1+s2 > maxSize 但是只有s2部分溢出;
- 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;
}
}