1.基本介绍
串,又称字符串,是由0个或者多个字符组成的有限序列,串结构存在的意义在于能方便的对字符常量进行增加删比较(C++中string类即封装了串数据类型)
2.串的构建
1.定长顺序数组(与初始化)
即直接在结构体中包含一个char类型顺序数组,用于存储元素
结构体
typedef struct sqString //定长顺序数组构建串
{
char a[MAXSIZE];
int len;
}*sqstring,sqstr;
对于基于定长顺序数组的构建方法,在分配结构体存储空间时也同时分配了数据存储空间(即数据和结构体本身存储位置相同)
初始化
sqstring SQcrease()
{
sqstring L;
L = (sqstring)malloc(sizeof(sqstr)); //在分配空间的时候实际上已经分配了a[MAXSIZE]的空间
L->len = 0;
return L;
}
2.基于堆的构建(与初始化)
即将数据和结构体本身分离,结构体中包含指向数据的指针而不包含数据本身,数据存储位于堆上
结构体
typedef struct sqString
{
char* a;
int len;
}*sqstring,sqstr;
初始化
初始化的时候同时需要对结构体本身以及数据分别分配存储空间
sqstring SQcrease()
{
sqstring L;
L = (sqstring)malloc(sizeof(sqstr)); //在分配结构体存储空间
L->a=(char*)malloc(sizeof(char)*MAXSIZE); //分配数据存储空间
L->len = 0;
return L;
}
3.基本操作
添加数据
直接从键盘输入
void Insert1(sqstring L,int n) //添加数据数据长度为n(这样定义函数需要每次都输入串长度)
{
char x;
if ((L->len + n) <= MAXSIZE)
{
for (int i = 0; i < n;i++)
{
cin >> x;
L->a[i + L->len] = x;
}
L->len += n;
}
}
从已有字符常量创建
void StrAssign(sqstr& T, char s[]) //转载自CSDN博主「自由不死」,从字符常量构建串(important)
{
T.len = 0;
for (; '\0' != s[T.len]; (T.len)++);
for (int i = 0; '\0' != s[i]; i++) //这里通过判断传入的参数的最后是否是一个空来判断是否结束(因为C/C++)使用'\0'作为数组结尾。
{
T.a[i] = s[i];
}
}
复制串到另一个串
sqstring copy(sqstring L) //复制串到另一个串
{
sqstring T;
T = SQcrease(); //初始化T
if (L->len != 0)
{
T->len = L->len;
for (int i = 0; i < (L->len) - 1; i++)
{
T[i] = L[i];
}
}
else
{
cout << "error" << endl;
}
return T;
}
判断是否为空串
bool StrEmpty(sqstring L) //判断是否为空串
{
if ((L->len) != 0)
{
cout << "TRUE" << endl;
return true;
}
else
{
cout << "FALSE" << endl;
return false;
}
}
清空串
void Clear(sqstring L) //清空串
{
for (int i = 0; i < L->len - 1; i++)
{
L->a[i] = '0';
}
L->len = 0;
}
联结串
相当于将两个串拼接,但是超过限制长度的部分将被舍弃
sqstring Connect(sqstring L,sqstring T) //联结串
{
sqstring S;
S = SQcrease(); //创建新串初始化
int k = 0;
if ((L->len) + (T->len) > MAXSIZE)
{
for (int i = 0; i < L->len; i++)
{
S->a[k] = L->a[i];
k = k + 1;
}
for (int i = 0; i < (MAXSIZE - L->len); i++)
{
S->a[k] = T->a[i];
k += 1;
}
S->len = MAXSIZE;
}
else
{
for (int i = 0; i < L->len; i++)
{
S->a[k] = L->a[i];
k = k + 1;
}
for (int i = 0; i < T->len; i++)
{
S->a[k] = T->a[i];
k += 1;
}
S->len = k;
}
return S;
}
打印串(输出串中存储元素)
平平无奇遍历小天才
void Print(sqstring L) //打印串
{
cout << "串长:" << L->len << endl;
cout << "串: " << "'";
for (int i = 0; i < L->len; i++)
{
cout << L->a[i] ;
}
cout << "'";
cout << endl;
}
销毁串
销毁基于定长数组的串
简单简单还是简单
void Distory(sqstring L) //销毁串
{
free(L);
L = NULL; //释放空间同时指针指向空
}
销毁基于堆的串
同时需要释放堆上的数据存储空间和结构体本身的存储空间
void Distory(sqstring L) //销毁串
{
free(L->a);
L->a=NULL;
free(L);
L = NULL; //释放空间同时指针指向空
}
4.两种构建方式的比较
使用定长数组构建可以发现明显操作更加复杂(明显一个指针比两个指针用起来方便嘛)
但是在堆上构建存储空间可以很方便的使用realloc函数重新分配扩展空间,基于数组的这样操作显然更加困难。
5.完整代码
#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
const int MAXSIZE = 255;
typedef struct sqString
{
char a[MAXSIZE];
int len;
}*sqstring,sqstr;
sqstring SQcrease()
{
sqstring L;
L = (sqstring)malloc(sizeof(sqstr)); //在分配空间的时候实际上已经分配了a[MAXSIZE]的空间
L->len = 0;
return L;
}
void Insert1(sqstring L,int n) //添加数据数据长度为n(这样定义函数需要每次都输入串长度)
{
char x;
if ((L->len + n) <= MAXSIZE)
{
for (int i = 0; i < n;i++)
{
cin >> x;
L->a[i + L->len] = x;
}
L->len += n;
}
}
void StrAssign(sqstr& T, char s[]) //转载自CSDN博主「自由不死」,从字符常量构建串(important)
{
T.len = 0;
for (; '\0' != s[T.len]; (T.len)++);
for (int i = 0; '\0' != s[i]; i++) //这里通过判断传入的参数的最后是否是一个空来判断是否结束(因为C/C++)使用'\0'作为数组结尾。
{
T.a[i] = s[i];
}
}
sqstring copy(sqstring L) //复制串到另一个串
{
sqstring T;
T = SQcrease(); //初始化T
if (L->len != 0)
{
T->len = L->len;
for (int i = 0; i < (L->len) - 1; i++)
{
T[i] = L[i];
}
}
else
{
cout << "error" << endl;
}
return T;
}
bool StrEmpty(sqstring L) //判断是否为空串
{
if ((L->len) != 0)
{
cout << "TRUE" << endl;
return true;
}
else
{
cout << "FALSE" << endl;
return false;
}
}
void Clear(sqstring L) //清空串
{
for (int i = 0; i < L->len - 1; i++)
{
L->a[i] = '0';
}
L->len = 0;
}
sqstring Connect(sqstring L,sqstring T) //联结串
{
sqstring S;
S = SQcrease(); //创建新串初始化
int k = 0;
if ((L->len) + (T->len) > MAXSIZE)
{
for (int i = 0; i < L->len; i++)
{
S->a[k] = L->a[i];
k = k + 1;
}
for (int i = 0; i < (MAXSIZE - L->len); i++)
{
S->a[k] = T->a[i];
k += 1;
}
S->len = MAXSIZE;
}
else
{
for (int i = 0; i < L->len; i++)
{
S->a[k] = L->a[i];
k = k + 1;
}
for (int i = 0; i < T->len; i++)
{
S->a[k] = T->a[i];
k += 1;
}
S->len = k;
}
return S;
}
void Print(sqstring L) //打印串
{
cout << "串长:" << L->len << endl;
cout << "串: " << "'";
for (int i = 0; i < L->len; i++)
{
cout << L->a[i] ;
}
cout << "'";
cout << endl;
}
void Distory(sqstring L) //销毁串
{
free(L);
L = NULL; //释放空间同时指针指向空
}
int main()
{
sqstring L = SQcrease();
sqstring T = SQcrease();
sqstring S = SQcrease();
sqstring C = SQcrease();
Insert1(L, 10); //这个用"helloworld"
Insert1(T, 8); //这个用"helloC++"
Print(L);
Print(T);
S = copy(L);
Print(S);
C = Connect(L, T);
Print(C);
Clear(S);
Print(S);
}