定长顺序结构的实现
一、定长顺序结构的概述
定长顺序结构 是类似于线性表的顺序存储结构,使用一组连续的存储单元存储串值的字符序列。
二、串的定长顺序存储表示
# define MAXSTRLEN 40//用户可以在255以内定义最大串长
typedef unsigned char SString[MAXSTRLEN + 1];//0号单元存放串的长度
串的实际长度可在这个预定义长度范围内随意,超出预定义长度的串则会被舍去,这称之为“截断”。
三、串的两种表示方法
1、0号单元存放串的长度
如上述定义的那样,一下标为0的数组分量存放串的实际长度。
2、串值后加"\0"
即在串值后加入一个不计入串长的结束标记字符。此时串长是一个隐含值,不变域操作。
四、串的操作
//1、生成一个其值等于chars的字符串T
bool StrAssign(SString T, char *chars);
//2、由串T复制得串S
void StrCopy(SString S, SString T);
//3、若S为空串,则返回true,否则返回false
bool StrEmpty(SString S);
//4、字符串长短比较,返回S长度-T长度
int StrCompare(SString S, SString T);
//5、返回串S的元素个数
int StrLength(SString S);
//6、显示串的值
void Strshow(SString S);
//7、串的拼接 S1后接S2,结果在T中。
bool StrConcat1(SString T, SString S1, SString S2);
//8、串的拼接 S1后接S2,结果放在S1中
bool StrConcat2(SString S1, SString S2);
//9、用Sub返回串S的第pos个字符起(包括pos位置处的字符)长度为len的子串。
bool SubString(SString Sub, SString S, int pos, int len);
//10、清空串
void ClearString(SString S);
//11、 返回子串T在主串S中的位置。若不存在,则函数值为0,其中,T非空。
int Index1(SString S, SString T);
//12、 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0,其中,T非空,1≤pos≤StrLength(S)。
int Index2(SString S, SString T, int pos);
//13、在串S的第pos个字符之前插入串T。完全插入返回true,部分插入返回false
bool StrInsert(SString S, int pos, SString T);
//14、从串S中删除第pos个字符起长度为len的子串
bool StrDelete(SString S, int pos, int len);
五、串操作的实现
1、生成一个其值等于chars的字符串T
bool StrAssign(SString T, char *chars)
{
int i;
if (strlen(chars) > MAX_STR_LEN)//chars 的长度大于最大长度,返回false
return false;
else
{
T[0] = strlen(chars); // 0号单元存放串的长度
for (i = 1; i <= T[0]; i++)//从1号单元开始复制串的内容
{
T[i] = *(chars + i - 1);//等价于T[i] = chars[i-1];
}
return true;
}
}
2、由串S复制得串T
void StrCopy(SString T, SString S)
{
int i;
for (i = 0; i <= S[0]; i++)
T[i] = S[i];
}
3、若S为空串,则返回true,否则返回false
//3、若S为空串,则返回true,否则返回false
bool StrEmpty(SString S)
{
if (S[0] == 0)
return true;
else
return false;
}
4、字符串长短比较,返回S长度-T长度
int StrCompare(SString S, SString T)
{// 初始条件:串S和T存在。
//操作结果:若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
int i;
for (i = 1; i <= S[0] && i <= T[0]; ++i)
if (S[i] != T[i])
return S[i] - T[i];
return S[0] - T[0];
}
5、返回串S的元素个数
int StrLength(SString S)
{
return S[0];
}
6、显示串的值
void Strshow(SString S)
{
int i;
for (i = 1; i <= S[0]; i++)//从1号单元开始逐单元输出串中的字符
{
printf(" %c", S[i]);
}
printf("\n");
}
7、串的拼接 S1后接S2,结果放在T中
当S1和S2的长度加在一起超出MAX_STR_LEN时,S2会被截断
bool StrConcat1(SString T, SString S1, SString S2)
{ // 用T返回S1和S2联接而成的新串。若未截断,则返回true,否则false
int i;
if (S1[0] + S2[0] <= MAX_STR_LEN)
{ // 未截断
for (i = 1; i <= S1[0]; i++)//先放S[1]到T中
T[i] = S1[i];
for (i = 1; i <= S2[0]; i++)//接着放S[2]到T中
T[S1[0] + i] = S2[i];
T[0] = S1[0] + S2[0];
return true;
}
else
{ // 截断S2
for (i = 1; i <= S1[0]; i++)//先放S[1]到T中
T[i] = S1[i];
for (i = 1; i <= MAX_STR_LEN - S1[0]; i++)//关键,若第一个串长度超过MAX_STR_LEN 则条件不成立,这里循环的次数为,S1剩余空间单位数
T[S1[0] + i] = S2[i];
T[0] = MAX_STR_LEN;
return false;
}
}
8、串的拼接 S1后接S2,结果放在S1中
bool StrConcat2(SString S1, SString S2)
{ // 用T返回S1和S2联接而成的新串。若未截断,则返回true,否则false
int i = 1;
int lens1 = S1[0];//保存S1的长度
while (i <= (MAX_STR_LEN - S1[0]) && i<= S2[0])//i小于等于除去S1长度剩余的长度&&i小于S2的长度
{
S1[S1[0] + i] = S2[i];//逐字符赋值
i++;
}
S1[0] = S1[0] + i - 1;//更新S1长度
if ((lens1 + S2[0]) <= MAX_STR_LEN)//判断有没有截断
return true;
else
return false;
}
9、用Sub返回串S的第pos个字符起(包括pos位置处的字符)长度为len的子串。
bool SubString(SString Sub, SString S, int pos, int len)
{
int i;
if (pos<1 || pos>S[0] || len<0 || len>S[0] - pos + 1)//排除pos值不在S长度范围内的值和len值+pos值超出S长度
return false;
for (i = 1; i <= len; i++)
Sub[i] = S[pos + i - 1];//包括pos位置处的字符
Sub[0] = len;
return true;
}
10、清空串
void ClearString(SString S)
{ // 初始条件:串S存在。
//操作结果:将S清为空串
S[0] = 0; // 令串长为零
}
11、 返回子串T在主串S中的位置。若不存在,则函数值为0,其中,T非空
int Index1(SString S, SString T)
{
int i = 1, j = 1;
for ( i = 1; i <=S[0]; i++)//循环主串
{
if (S[i]==T[1])//如果在主串中找到一个与子串的第一个字符相等的字符时
{
int cont = 1;//计数变量
for ( j = 1; j <=T[0]; j++)//遍历子串
{
if (T[j + 1] != S[i + j])//在遍历T[0]时如果有不一致时退出遍历
{
break;
}
else//否则计数
{
cont++;
if (cont == T[0])//当有T[0]个字符相同时则找到子串位置
return i;
}
}
}
continue;
}
return 0;//不存在时
}
12、 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0,其中,T非空,1≤pos≤StrLength(S)。
int Index2(SString S, SString T, int pos)
{
int i, j;
if (1 <= pos && pos <= S[0])
{
i = pos;//从主串的第pos个字符开始和子串的第一个字符比较
j = 1;
while (i <= S[0] && j <= T[0])
{
if (S[i] == T[j]) // 若第一个字符比较后相等则继续比较后继字符
{
++i;
++j;
}
else //若第一个字符不叫后不相等则后移一个位置重新开始匹配
{
i = i - j + 2;
j = 1;
}
}
if (j > T[0])//条件成立表示子串中的所有字符都能匹配相等,即主串中包含子串
return i - T[0];
else
return 0;
}
else
return 0;
}
13、在串S的第pos个字符之前插入串T。完全插入返回true,部分插入返回false
bool StrInsert(SString S, int pos, SString T)
{ // 初始条件:串S和T存在,1≤pos≤StrLength(S)+1
// 操作结果:在串S的第pos个字符之前插入串T,第pos个位置插入T[1]。完全插入返回true,部分插入返回false
int i;
if (pos<1 || pos>S[0] + 1)//插入位置不在S长度范围之内
return false;
if (S[0] + T[0] <= MAX_STR_LEN)
{ // 完全插入
for (i = S[0]; i >= pos; i--)//pos之后的元素后移T[0]个长度
S[i + T[0]] = S[i];
for (i = pos; i < pos + T[0]; i++)//插入
S[i] = T[i - pos + 1];
S[0] += T[0];//更新长度
return true;
}
else
{ // 部分插入
for (i = MAX_STR_LEN; i >= pos + T[0]; i--)//移动串S中位于pos之后仍在串内的字符,因为(S[0] + T[0] > MAX_STR_LEN)所S串插入T后必满, pos + T[0]是插入元素和pos及pos之前元素所占位置
S[i] = S[i - T[0]];
for (i = pos; i < pos + T[0] && i <= MAX_STR_LEN; i++)
S[i] = T[i - pos + 1];
S[0] = MAX_STR_LEN;//S的长度为最大
return false;//部分插入
}
}
14、从串S中删除第pos个字符起长度为len的子串
bool StrDelete(SString S, int pos, int len)
{ // 初始条件:串S存在,1≤pos≤StrLength(S)-len+1
// 操作结果:从串S中删除第pos个字符起长度为len的子串
int i;
if (pos<1 || pos>S[0] - len + 1 || len < 0)//pos和len的值超出范围
return false;
for (i = pos + len; i <= S[0]; i++)//循环删除子串后的所有字符
S[i - len] = S[i];//向前移动len个位置
S[0] -= len;//更新串S的长度
return true;
}
最后给出完整代码
// 串的定长顺序存储结构.cpp
#include<string.h>
#include<malloc.h> // malloc()等
#include<stdio.h> // EOF(=^Z或F6),NULL
#include<stdlib.h> // atoi()
#define MAX_STR_LEN 40 // 用户可在255(1个字节)以内定义最大串长
typedef char SString[MAX_STR_LEN + 1]; // 0号单元存放串的长度
// SString是数组,故不需引用类型
//1、生成一个其值等于chars的字符串T
bool StrAssign(SString T, char *chars);
//2、由串T复制得串S
void StrCopy(SString S, SString T);
//3、若S为空串,则返回true,否则返回false
bool StrEmpty(SString S);
//4、字符串长短比较,返回S长度-T长度
int StrCompare(SString S, SString T);
//5、返回串S的元素个数
int StrLength(SString S);
//6、显示串的值
void Strshow(SString S);
//7、串的拼接 S1后接S2,结果在T中。
bool StrConcat1(SString T, SString S1, SString S2);
//8、串的拼接 S1后接S2,结果放在S1中
bool StrConcat2(SString S1, SString S2);
//9、用Sub返回串S的第pos个字符起(包括pos位置处的字符)长度为len的子串。
bool SubString(SString Sub, SString S, int pos, int len);
//10、清空串
void ClearString(SString S);
//11、 返回子串T在主串S中的位置。若不存在,则函数值为0,其中,T非空。
int Index1(SString S, SString T);
//12、 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0,其中,T非空,1≤pos≤StrLength(S)。
int Index2(SString S, SString T, int pos);
//13、在串S的第pos个字符之前插入串T。完全插入返回true,部分插入返回false
bool StrInsert(SString S, int pos, SString T);
//14、从串S中删除第pos个字符起长度为len的子串
bool StrDelete(SString S, int pos, int len);
int main()
{
char c[MAX_STR_LEN + 1];
SString T;
printf("请输入串T: ");
gets_s(c);//接收字符串
printf("输入的字符串为 %s\n", c);
printf("输入的字符串长度为 %d\n", strlen(c));
if (!StrAssign(T, c))
{
printf("串长超过MAX_STR_LEN(=%d)\n", MAX_STR_LEN);
exit(0);
}
Strshow(T);
printf("T长度为 %d\n", StrLength(T));
///
SString S;
StrCopy(S, T);
Strshow(S);
///
if (StrEmpty(S))
{
printf("串S为空!\n");
}
else
{
printf("串S不为空!\n");
}
printf("比较S和T的长度结果 %d\n", StrCompare(S, T));
SString S1, S2;
printf("请输入串s1: ");
gets_s(c);//接收字符串
printf("输入的字符串S1为 %s\n", c);
printf("输入的字符串S1长度为 %d\n", strlen(c));
StrAssign(S1, c);
printf("请输入串s2: ");
gets_s(c);//接收字符串
StrAssign(S2, c);
printf("输入的字符串S2为 %s\n", c);
printf("输入的字符串S2长度为 %d\n", strlen(c));
StrConcat1(T, S1, S2);
Strshow(T);
StrConcat2(S1, S2);
Strshow(S1);
printf("字符串S1长度为 %d\n", S1[0]);
printf("T在S1中的位置为 %d\n",Index1(S1, S2));
int pos = 3, len = 2;
printf("T在S1中的位置为 %d\n",Index2(S1, S2,pos));
StrInsert(S1, pos, T);
Strshow(S1);
StrDelete(S1, pos,len);
Strshow(S1);
return 0;
}
//1、生成一个其值等于chars的字符串T
bool StrAssign(SString T, char *chars)
{
int i;
if (strlen(chars) > MAX_STR_LEN)//chars 的长度大于最大长度,返回false
return false;
else
{
T[0] = strlen(chars); // 0号单元存放串的长度
for (i = 1; i <= T[0]; i++)//从1号单元开始复制串的内容
{
T[i] = *(chars + i - 1);//等价于T[i] = chars[i-1];
}
return true;
}
}
//2、由串T复制得串S
void StrCopy(SString S, SString T )
{
int i;
for (i = 0; i <= T[0]; i++)
S[i] = T[i];
}
//3、若S为空串,则返回true,否则返回false
bool StrEmpty(SString S)
{
if (S[0] == 0)
return true;
else
return false;
}
//4、字符串长短比较,返回S长度-T长度
int StrCompare(SString S, SString T)
{// 初始条件:串S和T存在。
//操作结果:若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
int i;
for (i = 1; i <= S[0] && i <= T[0]; ++i)
if (S[i] != T[i])
return S[i] - T[i];
return S[0] - T[0];
}
//5、返回串S的元素个数
int StrLength(SString S)
{
return S[0];
}
//6、显示串的值
void Strshow(SString S)
{
int i;
for (i = 1; i <= S[0]; i++)//从1号单元开始逐单元输出串中的字符
{
printf(" %c", S[i]);
}
printf("\n");
}
//7、串的拼接 S1后接S2,结果放在T中
bool StrConcat1(SString T, SString S1, SString S2)
{ // 用T返回S1和S2联接而成的新串。若未截断,则返回true,否则false
int i;
if (S1[0] + S2[0] <= MAX_STR_LEN)
{ // 未截断
for (i = 1; i <= S1[0]; i++)//先放S[1]到T中
T[i] = S1[i];
for (i = 1; i <= S2[0]; i++)//接着放S[2]到T中
T[S1[0] + i] = S2[i];
T[0] = S1[0] + S2[0];
return true;
}
else
{ // 截断S2
for (i = 1; i <= S1[0]; i++)//先放S[1]到T中
T[i] = S1[i];
for (i = 1; i <= MAX_STR_LEN - S1[0]; i++)//关键,若第一个串长度超过MAX_STR_LEN 则条件不成立
T[S1[0] + i] = S2[i];
T[0] = MAX_STR_LEN;
return false;
}
}
//8、串的拼接 S1后接S2,结果放在S1中
bool StrConcat2(SString S1, SString S2)
{ // 用T返回S1和S2联接而成的新串。若未截断,则返回true,否则false
int i = 1;
int lens1 = S1[0];//保存S1的长度
while (i <= (MAX_STR_LEN - S1[0]) && i<= S2[0])//i小于等于除去S1长度剩余的长度&&i小于S2的长度
{
S1[S1[0] + i] = S2[i];//逐字符赋值
i++;
}
S1[0] = S1[0] + i - 1;//更新S1长度
if ((lens1 + S2[0]) <= MAX_STR_LEN)//判断有没有截断
return true;
else
return false;
}
//9、用Sub返回串S的第pos个字符起(包括pos位置处的字符)长度为len的子串。
bool SubString(SString Sub, SString S, int pos, int len)
{
int i;
if (pos<1 || pos>S[0] || len<0 || len>S[0] - pos + 1)//排除pos值不在S长度范围内的值和len值+pos值超出S长度
return false;
for (i = 1; i <= len; i++)
Sub[i] = S[pos + i - 1];//包括pos位置处的字符
Sub[0] = len;
return true;
}
//10、清空串
void ClearString(SString S)
{ // 初始条件:串S存在。
//操作结果:将S清为空串
S[0] = 0; // 令串长为零
}
//11、 返回子串T在主串S中的位置。若不存在,则函数值为0,其中,T非空。
int Index1(SString S, SString T)
{
int i = 1, j = 1;
for ( i = 1; i <=S[0]; i++)//循环主串
{
if (S[i]==T[1])//如果在主串中找到一个与子串的第一个字符相等的字符时
{
int cont = 1;//计数变量
for ( j = 1; j <=T[0]; j++)//遍历子串
{
if (T[j + 1] != S[i + j])//在遍历T[0]时如果有不一致时退出遍历
{
break;
}
else//否则计数
{
cont++;
if (cont == T[0])//当有T[0]个字符相同时则找到子串位置
return i;
}
}
}
continue;
}
return 0;//不存在时
}
//12、 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0,其中,T非空,1≤pos≤StrLength(S)。
int Index2(SString S, SString T, int pos)
{
int i, j;
if (1 <= pos && pos <= S[0])
{
i = pos;//从主串的第pos个字符开始和子串的第一个字符比较
j = 1;
while (i <= S[0] && j <= T[0])
{
if (S[i] == T[j]) // 继续比较后继字符
{
++i;
++j;
}
else // 指针后退重新开始匹配
{
i = i - j + 2;
j = 1;
}
}
if (j > T[0])
return i - T[0];
else
return 0;
}
else
return 0;
}
//13、在串S的第pos个字符之前插入串T。完全插入返回true,部分插入返回false
bool StrInsert(SString S, int pos, SString T)
{ // 初始条件:串S和T存在,1≤pos≤StrLength(S)+1
// 操作结果:在串S的第pos个字符之前插入串T,第pos个位置插入T[1]。完全插入返回true,部分插入返回false
int i;
if (pos<1 || pos>S[0] + 1)//插入位置不在S长度范围之内
return false;
if (S[0] + T[0] <= MAX_STR_LEN)
{ // 完全插入
for (i = S[0]; i >= pos; i--)//pos之后的元素后移T[0]个长度
S[i + T[0]] = S[i];
for (i = pos; i < pos + T[0]; i++)//插入
S[i] = T[i - pos + 1];
S[0] += T[0];//更新长度
return true;
}
else
{ // 部分插入
for (i = MAX_STR_LEN; i >= pos + T[0]; i--)//移动串S中位于pos之后仍在串内的字符,因为(S[0] + T[0] > MAX_STR_LEN)所S串插入T后必满, pos + T[0]是插入元素和pos及pos之前元素所占位置
S[i] = S[i - T[0]];
for (i = pos; i < pos + T[0] && i <= MAX_STR_LEN; i++)
S[i] = T[i - pos + 1];
S[0] = MAX_STR_LEN;//S的长度为最大
return false;//部分插入
}
}
//14、从串S中删除第pos个字符起长度为len的子串
bool StrDelete(SString S, int pos, int len)
{ // 初始条件:串S存在,1≤pos≤StrLength(S)-len+1
// 操作结果:从串S中删除第pos个字符起长度为len的子串
int i;
if (pos<1 || pos>S[0] - len + 1 || len < 0)//pos和len的值超出范围
return false;
for (i = pos + len; i <= S[0]; i++)//循环删除子串后的所有字符
S[i - len] = S[i];//向前移动len个位置
S[0] -= len;//更新串S的长度
return true;
}