1.串的基本概念
串:由零个或多个字符组成的有限序列。
子串:一个串中任意个连续字符组成的序列。
如串 “abcde”,的子串有 “a”、“b”、“ab”、“abc”、“abcde” 等。
串和线性表一样,也有顺序存储结构(顺序串)和链式存储结构(链串)。
2.顺序串
顺序串存储方式有:非紧缩格式,紧缩格式。
一个字节可以表示一个字符。由于计算机内存是按字编址的,即以字为存储单位,一个存储单元指的是一个字。而一个字可能包含多个字节,不同的计算机系统的字长是不同的,常见的有8位、16位、32位、64位等,字长越长,计算机一次处理的信息位就越多,精度就越高,字长是计算机性能的一个重要指标。
一个32位的CPU字长是4个字节。下图是32位的CPU的机器顺序串的存储方式。
串的紧缩格式节省空间,但处理单个字符不方便,运行效率低,因为要花费时间从同一个字中分离出字符;非紧缩格式则相反。因此对串的操作主要采用非紧缩格式。对于非紧缩格式的顺序串类型声明格式如下
typedef struct
{
char data[MaxSize]; //存放串字符
int length; //存放串长
}SqString;
串的实现
#include<stdlib.h>
#include<stdio.h>
//定义串的类型
#define MaxSize 50
typedef struct
{
char data[MaxSize]; //存放串字符
int length; //存放串长
}SqString;
//生成串
void StrAssign(SqString &s, char cstr[]) //s为引用型参数
{
int i;
for (i = 0; cstr[i] != '\0'; i++)
s.data[i] = cstr[i];
s.length = i; //设置串s长度
}
//输出串的值
void DispStr(SqString s)
{
int i;
if (s.length > 0)
{
for (i = 0; i < s.length; i++)
printf("%c", s.data[i]);
printf("\n");
}
}
//串的复制
void StrCopy(SqString &s, SqString t)
{
int i;
for (i = 0; i<t.length; i++)
s.data[i] = t.data[i];
s.length = t.length;
}
//判断串是否相等
bool StrEqual(SqString s, SqString t)
{
bool flag = true;
int i;
if (s.length != t.length) //长度不相等返回false
flag = false;
else
for (i = 0; i < s.length; i++)
if (s.data[i] != t.data[i]) //有一个对应的字符不相等返回false
{
flag = false;
break;
}
return flag;
}
//求串长
int StrLength(SqString s)
{
return s.length;
}
//将两个串连接
SqString Concat(SqString s, SqString t)
{
SqString str; //定义结果串
int i;
for (i = 0; i < s.length; i++)
str.data[i] = s.data[i];
for (i = 0; i < t.length; i++)
str.data[s.length+i] = t.data[i];
return str;
}
子串操作
1.返回顺序串s中从第i个字符开始的连续j个字符组成的子串。
SqString SubStr(SqString s, int i, int j)
{
int k;
SqString str; //定义结果串
str.length = 0;
if (i <= 0 || i > s.length || j<0 || i + j - 1>s.length)
//参数不正确时返回空串
return str;
for (k = i - 1; k < i + j - 1; k++)
//将s.data[0] 到 s.data[i+j-1] 的字符复制到str
str.data[k - i + 1] = s.data[k];
str.length = j;
return str;
}
2.将顺序串s2插入到顺序串s1的第 i 个位置上。
SqString InsStr(SqString s1, int i, SqString s2)
{
int j;
SqString str;
str.length = 0;
if (i <= 0 || i > s1.length + 1)
//参数不正确时返回空串
return str;
for (j = 0; j < i - 1; j++)
//将s1.data[0] 到 s1.data[i-2] 复制到str
str.data[j] = s1.data[j];
for (j = 0; j < s2.length; j++)
//将s2.data[0] 到 s2.data[s2.length-1] 复制到str
str.data[i + j - 1] = s2.data[j];
for (j = i - 1; j < s1.length; j++)
//将s1.data[i-1] 到 s1.data[s1.length-1] 复制到str
str.data[s2.length + j] = s1.data[j];
str.length = s1.length + s2.length;
return str;
}
3.在顺序串中删去从第 i 个字符开始的长度为 j 的子串。
SqString DelStr(SqString s, int i, int j)
{
int k;
SqString str;//定义结果串
str.length = 0;
if (i <= 0 || i > s.length || i + j >s.length+1)
//参数不正确,返回空串
return str;
for (k = 0; k < i - 1; k++)
str.data[k] = s.data[k];
for(k=i+j-1;k<s.length;k++)
str.data[k-j]=s.data[k];
str.length =s.length-j;
return str;
}
4.在顺序串s中将第 i 个字符开始的连续 j 个字符构成的子串用顺序串 t 替换。
SqString RepStr(SqString s, int i, int j,SqString t)
{
int k;
SqString str;//定义结果串
str.length = 0;
if (i <= 0 || i > s.length || j<0 || i + j - 1>s.length)
return str;
for (k = 0; k < i - 1; k++)
//将s.data[0] 到 s.data[i-2] 复制到str
str.data[k] = s.data[k];
for (k = 0; k < t.length; k++)
//将t.data[0] 到 s.data[t.length-1] 复制到str
str.data[i+k-1] = t.data[k];
for (k = i + j - 1; k<s.length; k++)
//将s.data[i+k-1] 到 s.data[s.length-1] 复制到str
str.data[t.length+k-j] = s.data[k];
str.length = s.length - j + t.length;
return str;
}