注:主函数中的操作和参数是直接以实参的形式放在了调用的函数中
"加油站"指的是解决 从头指针一直扫描到当前所需要的指针的繁杂问题 的办法,即如设置加油站一样在串中设置一些特定的指示性指针。(下图中的程序未用此方法)
#include<iostream>
#include<cstdio>
using namespace std;
const int OK = 1;
const int overflow = -2;
const int ERROR = 0;
const int TRUE = 1;
const int FALSE = 0;
const int CHUNKSIZE = 4;
typedef int Status;
typedef struct Chunk //结点
{
char ch[CHUNKSIZE];
struct Chunk* next;
}Chunk;
typedef struct //链表
{
Chunk* head;
Chunk* tail;
int curlen; //串的当前长度(结点数)
}LString;
const char blank = '#';//填补空余的标准
const char del = '@';//被删除的标志
/**************函数声明****************/
Status SLength(char S[]);
//返回数组S的长度
Status InitString(LString& T);
Status StrAssign(LString& T, char chars[]);
//生成一个值等于chars的串T
Status StrCopy(LString& T, LString S);
//由S复制得到串T
Status StrEmpty(LString S);
//若为空则返回TRUE
Status StrCompare(LString S, LString T);
//若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
Status StrLength(LString S);
Status ClearString(LString &S);
Status Concat(LString &S1, LString S2);
Status SubString(LString& Sub, LString S, int pos, int len);
//用Sub返回子串
Status index(LString S, LString T, int pos);
//若T非空,主串S中第pos个字符之后存在与T相等的子串
//则返回第一个这样的子串在S中的位置,否则返回0
Status StrInsert(LString& S, int pos, LString T);
//在S的第pos个结点之后插入串T
Status StrDelete(LString &S, int pos, int len);
Status Replace(LString &news, LString S, LString T, LString V);
//用V替换主串S中出现的所有与T相等的不重叠的子串
Status StrPrint(LString T);
//输出字符串T
Status DestoryString(LString& T);
/************主函数**********/
int main()
{
LString T1;
LString T2;
LString T3;
LString Sub1;
InitString(Sub1);
char S1[11] = {"012354" };
char S2[11] = { "012" };
InitString(T1);
StrAssign(T1, S1);
cout << "T1:";
StrPrint(T1);
cout << endl << endl;
cout << "输出复制T1后的T2:" << endl;
InitString(T2);
StrCopy(T2, T1);
cout << "T2:";
StrPrint(T2);
cout << endl << endl;
InitString(T3);
StrAssign(T3, S2);
cout << "T3:";
StrPrint(T3);
cout << endl << endl;
cout << "T1和T3的比较结果:" << endl;
if (StrCompare(T1, T3) > 0)
{
cout << "T1 > T3" << endl;
}
else if (StrCompare(T1, T3) < 0)
{
cout << "T1 < T3" << endl;
}
else
{
cout << "T1 = T3" << endl;
}
cout << "T1的(字符数)长度为:" << StrLength(T1);
Concat(T1, T3);
cout << endl << endl;
cout << "T1和T3合并之后的结果:" << endl;
StrPrint(T1);
cout << endl << endl;
cout << "插入T3后的T2:" << endl;
StrInsert(T2, 1, T3);//此处的1是指结点的位置,而不是某个元素的位置
StrPrint(T2);
cout << endl << endl;
SubString(Sub1, T2, 3, 7);
cout << "所返回的子串Sub1为:" << endl;
StrPrint(Sub1);
cout << endl << endl;
cout << "T3在T2的位置为:" << endl;
cout << "位于第" << index(T2, T3, 2) << "个字符";
cout << endl << endl;
StrDelete(T2, 2, 3);
cout << "删除指定元素后的串:" << endl;
StrPrint(T2);
return OK;
}
/*****************函数定义*******************/
Status SLength(char S[])
{
int count = 0;
int number = 0;
while (S[number] != '\0')
{
count++;
number++;
}
return count;
}
Status InitString(LString& T)
{
Chunk* p = (Chunk*)malloc(CHUNKSIZE * sizeof(Chunk));
if (!p)
{
exit(overflow);
}
T.head = p;
T.tail = T.head;
p->next = NULL;
T.curlen = 0;
return OK;
}
Status StrAssign(LString& T, char chars[])
{
int i;
int length = SLength(chars);
int num = length / CHUNKSIZE;
if (length % CHUNKSIZE)
{
num++;
}
T.curlen = num;//结点数量
for (i = 0; i < num; i++)
{
Chunk* p = (Chunk*)malloc(CHUNKSIZE * sizeof(Chunk));
if (!p)
{
exit(overflow);
}
T.tail->next = p;
T.tail = p;
if (i == num - 1 && (length % CHUNKSIZE) >= 1 && (length % CHUNKSIZE) < CHUNKSIZE)
{
for (int n = 0; n < (length % CHUNKSIZE); n++)
{
T.tail->ch[n] = chars[n + 4 * i];
}
for (int k = length % CHUNKSIZE; k <= (CHUNKSIZE - 1); k++)
{
T.tail->ch[k] = blank;
}
}
else
{
for (int m = 0; m < CHUNKSIZE; m++)
{
T.tail->ch[m] = chars[m + 4 * i];
}
T.tail->next = NULL;
}
}
return OK;
}
//生成一个值等于chars的串T
Status StrCopy(LString& T, LString S)
{
for (int i = 0; i < S.curlen; i++)
{
Chunk* p = (Chunk*)malloc(CHUNKSIZE * sizeof(Chunk));
if (!p)
{
exit(overflow);
}
T.tail->next = p;
T.tail = p;
for (int m = 0; m < CHUNKSIZE; m++)
{
T.tail->ch[m] = S.head->next->ch[m];
}
S.head = S.head->next;
}
T.curlen = S.curlen;
return OK;
}
//由S复制得到串T
Status StrEmpty(LString S)
{
if (S.curlen == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
//若为空则返回TRUE
Status StrCompare(LString S, LString T)
{
for (int i = 0; i < S.curlen && i < T.curlen; i++)
{
for (int j = 0; j < CHUNKSIZE; j++)
{
if (S.head->next->ch[j] != T.head->next->ch[j])
{
return S.head->next->ch[j] - T.head->next->ch[j];
}
}
S.head = S.head->next;
T.head = T.head->next;
}
return 0;
}
Status StrLength(LString S)
{
int count1 = S.curlen * CHUNKSIZE;
int count2 = 0;
for (int i = 0; i < CHUNKSIZE; i++)
{
if (S.tail->ch[i] == blank)
{
count2++;
}
}
return count1 - count2;
}
Status ClearString(LString &S)
{
S.tail = S.head;
S.curlen = 0;
return OK;
}
Status Concat(LString &S1, LString S2)
{
S1.tail->next = S2.head->next;
S1.tail = S2.tail;
S1.curlen = S1.curlen + S2.curlen;
return OK;
}
Status SubString(LString& Sub, LString S, int pos, int len) //(待改进)
{
int n;//子串(Sub)应包含的结点(块)数
n = len / CHUNKSIZE;
if (len % CHUNKSIZE)
{
n++;
}
Sub.curlen = n;
for (int i = 0; i < n; i++)
{
Chunk* p = (Chunk*)malloc(sizeof(Chunk) * CHUNKSIZE);
if (!p)
{
exit(overflow);
}
Sub.tail->next = p;
Sub.tail = p;
}
Chunk* q = NULL;//指向S中待操作块的指针
Chunk* k = NULL;//指向Sub中待操作块的指针
k = Sub.head->next;
int Nodeplace = pos / CHUNKSIZE; //第一个所求字符所在结点的位序
if (pos % CHUNKSIZE)
{
Nodeplace++;
}
for (int i = 0; i < Nodeplace; i++)
{
q = S.head->next; //"加油站"的问题
}
int Speplace = pos % CHUNKSIZE; //某字符在数组中的具体位置
for (int j = 0; j < len; j++)
{
if (Speplace != 1 && (Speplace ) % CHUNKSIZE == 1)
{
Speplace = Speplace - CHUNKSIZE;
q = q->next;
}
if (j != 0 && (j + 1) % CHUNKSIZE == 1)
{
k = k->next;//k = NULL error;
}
k-> ch[j % CHUNKSIZE] = q->ch[Speplace - 1];
Speplace++;
}
if (len % CHUNKSIZE != 0)
{
for (int i = len % CHUNKSIZE; i < CHUNKSIZE; i++)
{
k->ch[i] = blank;
}
}
return OK;
}
//用Sub返回子串
Status index(LString S, LString T, int pos)
{
int m; //T串长度
int n; //主串长度
int i;
LString sub;
InitString(sub);
if (StrLength(T) == 0)
{
return ERROR;
}
if (pos >= 1 && pos <= StrLength(S))
{
m = StrLength(T);
n = StrLength(S);
i = pos;
while (i <= n - m + 1)
{
SubString(sub, S, i, m);
if (StrCompare(sub, T) == 0)
{
return i;
}
else
{
i++;
}
}
}
return 0; //此处不写OK是为了表示没有符合条件的位序,用0表示
}
//定位函数![在这里插入图片描述](https://img-blog.csdnimg.cn/20200405181005191.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3d1cWlzZW45eg==,size_16,color_FFFFFF,t_70)
Status StrInsert(LString& S, int pos, LString T)
{
S.curlen = S.curlen + T.curlen;
Chunk* p = S.head; //中间变量
Chunk* q; //中间变量
for (int i = 0; i < pos; i++)//"加油站问题"(此处效率较低,需要改进)
{
p = p->next;
}
q = p->next;
p->next = T.head->next;
T.tail->next = q;
return OK;
}
//在S的第pos个结点之前插入串T
Status StrDelete(LString &S, int pos, int len)//未完成
{
Chunk* p = S.head; //作为移动的指针
int Nodeplace = 0; //被删除的字符串的第一个字符所在的结点位置
int Speplace = pos % CHUNKSIZE; //该串的第一个字符所在结点的具体位置
if ((pos % CHUNKSIZE) != 0)
{
Nodeplace = pos / CHUNKSIZE + 1;
}
else
{
Nodeplace = pos / CHUNKSIZE;
}
for (int i = 0; i < Nodeplace; i++)
{
p = p->next;
}
for (int i = 0; i < len; i++)
{
if (Speplace > CHUNKSIZE)
{
Speplace = Speplace - CHUNKSIZE;
p = p->next;
}
p->ch[Speplace - 1] = del;
Speplace++;
}
return OK;
}
Status StrPrint(LString T)
{
cout << "(主串的结点数为" << T.curlen << ')' << endl;
for (int i = 0; i < T.curlen; i++)
{
for (int j = 0; j < CHUNKSIZE; j++)
{
cout << T.head->next->ch[j] << ' ';
}
T.head = T.head->next;
}
return OK;
}
//输出字符串T
Status DestoryString(LString& T)
{
if (!T.head)
{
free(T.head);
}
T.head = NULL;
T.tail = NULL;
T.curlen = 0;
return OK;
}