说明:串的顺序存储操作,分为静态数组和动态数组两类。两者的操作差别不大,注意看动态数组前面的补充内容。
静态数组
//
// @Author: Brisa
// @Date: 2021/9/4
// @Description: 串的顺序存储
// 静态数组实现(定长顺序存储)
// 舍弃数组0号位,从1开始存取等操作
//
#include<stdio.h>
#include<string.h>
#define MAXLEN 255 //预定义最大串长为255
typedef struct{
char ch[MAXLEN]; //每个分两存储一个字符
int length; //串的实际长度
}SString;
/*函数声明*/
void StrAssign(SString &S, char chars[]); //1.赋值操作,把串S,赋值为chars
void StrCopy(SString &S, SString T); //2.复制操作,由串T复制得到S
bool StrEmpty(SString S); //3.判空操作,若S为空串返回true,否则返回false
int StrLength(SString S); //4.求串长,返回串S的个数
void ClearString(SString &S); //5.清空操作,将S清为空串
//bool DestroyString(SString &S); //6.销毁串,将串S销毁(回收存储空间)
void Concat(SString &S, SString T1, SString T2); //7.串连接,用S返回由T1和T2连接而成的新串
bool SubString(SString &Sub, SString S, int pos, int len); //8.求子串,用Sub返回串S中的第pos个字符起长度为len的子串
int StrCompare(SString S, SString T); //9.比较操作,若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
int Index(SString S, SString T); //10.定位操作,若主串S中存在与串T相同的子串,则返回它在子串中第一次出现的位置,否则函数值为0
void InitString(SString &S); //11.初始化串
void PrintString(SString S); //12.遍历串
/*基本操作的实现*/
//1.赋值操作,把串S,赋值为chars
void StrAssign(SString &S, char chars[]){
S.ch[0] = '#'; //0号位舍弃不用
for(int i=1; i<MAXLEN && i<=strlen(chars); i++) {
S.ch[i] = chars[i-1];
S.length++;
}
/*
int i = 0;
while(chars[i]){
T.ch[++T.length] = chars[i];
i++;
}
*/
}
//2.复制操作,由串T复制得到S
void StrCopy(SString &S, SString T){
for(int i=1; i<=T.length; i++){
S.ch[i] = T.ch[i];
}
S.length = T.length;
}
//3.判空操作,若S为空串返回true,否则返回false
bool StrEmpty(SString S){
return S.length == 0;
}
//4.求串长,返回串S的个数
int StrLength(SString S){
return S.length;
}
//5.清空操作,将S清为空串[逻辑上清空]
void ClearString(SString &S){
S.length = 0;
}
//6.销毁串,将串S销毁(回收存储空间)
//bool DestroyString(SString &S){} 静态数组,未使用时自动回收空间
//7.串连接,用S返回由T1和T2连接而成的新串
void Concat(SString &S, SString T1, SString T2){
S.length = 0;
for(int i=1; i<MAXLEN && i<= T1.length+T2.length; i++){
if(i <= T1.length){
S.ch[i] = T1.ch[i];
} else{
S.ch[i] = T2.ch[i-T1.length];
}
S.length++;
/*先将S1赋值给T,等价于 StrCopy(T, S1);*/
/*for (int i = 1; i <= S1.length; i++)
T.ch[i] = S1.ch[i];
for (int i = 1; i <= S2.length; i++)
T.ch[i + S1.length] = S2.ch[i];
T.length = S1.length + S2.length;
*/
}
}
//8.求子串,用Sub返回串S中的第pos个字符起长度为len的子串
bool SubString(SString &Sub, SString S, int pos, int len){
if((pos + len-1) > S.length)//判断子串范围是否越界
return false;
for (int i=pos; i <= pos+len-1; i++){
Sub.ch[i-pos+1] = S.ch[i];
}
Sub.length = len;
return true;
}
//9.比较操作,若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
int StrCompare(SString S, SString T){
for(int i=1; i<=S.length && i<=T.length; i++){
if(S.ch[i] != T.ch[i])
return S.ch[i] - T.ch[i];
}
//前面的都相等,就比较串长
return S.length - T.length;
}
//10.定位操作,若主串S中存在与串T相同的子串,则返回它在子串中第一次出现的位置,否则函数值为0
int Index(SString S, SString T){
int i=1, n=S.length, m=T.length;
SString Sub; //用于暂存子串
while(i < n-m+1){
SubString(Sub, S, i, m);
/*相当于从S的开头找遍 长度为m 的子串,再与T进行比较*/
if(StrCompare(Sub, T) != 0) {
i++;
} else
return i; //若相等则返回T在S中的位置
}
return 0; //S中不存在与T相等的子串
}
//11.初始化串
void InitString(SString &S){
S.length = 0;
}
//12.遍历串
void PrintString(SString S){
int i=1;
while (i<=S.length)
printf("%c ", S.ch[i++]);
printf("\n");
}
int main(){
//1.定义一个静态定长串
SString S1;
//2.初始化该串
InitString(S1);
//3.赋值操作
printf("***开始赋值操作***\n");
char chars[] = "hello,world";
StrAssign(S1, chars);
PrintString(S1);
//4.复制操作
printf("***开始复制操作***\n");
SString S2;
StrCopy(S2, S1);
PrintString(S2);
//5.连接操作
printf("***开始连接操作***\n");
SString S3;
Concat(S3, S1, S2);
PrintString(S3);
//6.求子串操作
printf("***开始求子串操作***\n");
SString Sub;
int pos = 3, len = 4;
if(SubString(Sub, S1, pos, len)){
printf("所得子串为:");
PrintString(Sub);
} else {
printf("子串范围越界\n");
}
//7.比较操作
printf("***开始比较操作***\n");
if(StrCompare(S1,S2) == 0){
printf("S1 = S2\n");
} else if(StrCompare(S1,S2) > 0){
printf("S1 > S2\n");
} else{
printf("S1 < S2\n");
}
//8.定位操作
printf("***开始定位操作***\n");
if(Index(S1,Sub) != 0){
printf("子串Sub在S1中的位置为:%d\n", Index(S1,Sub));
} else{
printf("子串Sub不在S1中\n");
}
//9.一些其他函数的实现
printf("S1的长度为:%d\n",StrLength(S1));
ClearString(S1);
printf("S1的长度为:%d\n",StrLength(S1));
return 0;
}
动态数组
//
// @Author: Brisa
// @Date: 2021/9/4
// @Description: 串的顺序存储
// 动态数组实现(堆分配存储)
// 补充:相较于静态数组申请方式,1)只是在销毁串方面有差异,
// 2)再就是增加了一个扩大串长的函数,
// 3)以及声明了串后,都需要先InitString 初始化一下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXLEN 255 //预定义最大串长为255
typedef struct{
char *ch; //按串长分配存储区,ch指向串的基地址
int length; //串的实际长度
}HString;
/*函数声明*/
void StrAssign(HString &S, char chars[]); //1.赋值操作,把串S,赋值为chars
void StrCopy(HString &S, HString T); //2.复制操作,由串T复制得到S
bool StrEmpty(HString S); //3.判空操作,若S为空串返回true,否则返回false
int StrLength(HString S); //4.求串长,返回串S的个数
void ClearString(HString &S); //5.清空操作,将S清为空串
void DestroyString(HString &S); //6.销毁串,将串S销毁(回收存储空间)
void Concat(HString &S, HString T1, HString T2); //7.串连接,用S返回由T1和T2连接而成的新串
bool SubString(HString &Sub, HString S, int pos, int len); //8.求子串,用Sub返回串S中的第pos个字符起长度为len的子串
int StrCompare(HString S, HString T); //9.比较操作,若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
int Index(HString S, HString T); //10.定位操作,若主串S中存在与串T相同的子串,则返回它在子串中第一次出现的位置,否则函数值为0
void InitString(HString &S); //11.初始化串
void PrintString(HString S); //12.遍历串
void IncreaseSize(HString& S, int len); //13.增加串长
/*函数实现*/
//1.赋值操作,把串S,赋值为chars
void StrAssign(HString &S, char chars[]){
int i = 0;
while (chars[i])
{
S.ch[++S.length] = chars[i];
i++;
}
}
//2.复制操作,由串T复制得到S
void StrCopy(HString &S, HString T){
for(int i=1; i<=T.length; i++){
S.ch[i] = T.ch[i];
}
S.length = T.length;
}
//3.判空操作,若S为空串返回true,否则返回false
bool StrEmpty(HString S){
return S.length == 0;
}
//4.求串长,返回串S的个数
int StrLength(HString S){
return S.length;
}
//5.清空操作,将S清为空串(逻辑上清空)
void ClearString(HString &S){
S.length = 0;
}
//6.销毁串,将串S销毁(回收存储空间)
void DestroyString(HString &S){
free(S.ch); //清除掉S.ch
S.ch = NULL;
}
//7.串连接,用S返回由T1和T2连接而成的新串
void Concat(HString &S, HString T1, HString T2){
/*先将S1赋值给S2,等价于 StrCopy(T, S1);*/
for (int i = 1; i <= T1.length; i++)
S.ch[i] = T1.ch[i];
for (int i = 1; i <= T2.length; i++)
S.ch[i + T1.length] = T2.ch[i];
S.length = T1.length + T2.length;
}
//8.求子串,用Sub返回串S中的第pos个字符起长度为len的子串
bool SubString(HString &Sub, HString S, int pos, int len){
if((pos + len-1) > S.length)//判断子串范围是否越界
return false;
for (int i=pos; i <= pos+len-1; i++){
Sub.ch[i-pos+1] = S.ch[i];
}
Sub.length = len;
return true;
}
//9.比较操作,若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
int StrCompare(HString S, HString T){
for(int i=1; i<=S.length && i<=T.length; i++){
if(S.ch[i] != T.ch[i])
return S.ch[i] - T.ch[i];
}
//前面的都相等,就比较串长
return S.length - T.length;
}
//10.定位操作,若主串S中存在与串T相同的子串,则返回它在子串中第一次出现的位置,否则函数值为0
int Index(HString S, HString T){
int i=1, n=S.length, m=T.length;
HString Sub; //用于暂存子串
InitString(Sub);
while(i < n-m+1){
SubString(Sub, S, i, m);
/*相当于从S的开头找遍 长度为m 的子串,再与T进行比较*/
if(StrCompare(Sub, T) != 0) {
i++;
} else
return i; //若相等则返回T在S中的位置
}
return 0; //S中不存在与T相等的子串
}
//11.初始化串
void InitString(HString &S){
S.ch = (char *)malloc(sizeof(char) * MAXLEN);
S.length = 0;
}
//12.遍历串
void PrintString(HString S){
for (int i = 1; i <= S.length; i++)
printf("%c ", S.ch[i]);
printf("\n");
}
//13.增加动态数组的长度
void IncreaseSize(HString& S, int len){
char *p= S.ch;
S.ch = (char *)malloc(sizeof(char) * (MAXLEN + len));
for(int i=1; i<= S.length; i++){ //将数据复制到新区域(时间开销大)
S.ch[i] = p[i];
}
S.length += len; //串长增加len
free(p); // 释放掉原来的内存空间
}
int main(){
//1.声明一个动态串
HString S1;
//2.初始化一个串
InitString(S1);
//3.赋值操作
printf("***开始赋值操作***\n");
char chars[] = "hello,world";
StrAssign(S1, chars);
PrintString(S1);
//4.复制操作
printf("***开始复制操作***\n");
HString S2;
InitString(S2);
StrCopy(S2, S1);
PrintString(S2);
//5.连接操作
printf("***开始连接操作***\n");
HString S3;
InitString(S3);
Concat(S3, S1, S2);
PrintString(S3);
//6.求子串操作
printf("***开始求子串操作***\n");
HString Sub;
InitString(Sub);
int pos = 3, len = 4;
if(SubString(Sub, S1, pos, len)){
printf("所得子串为:");
PrintString(Sub);
} else {
printf("子串范围越界\n");
}
//7.比较操作
printf("***开始比较操作***\n");
if(StrCompare(S1,S2) == 0){
printf("S1 = S2\n");
} else if(StrCompare(S1,S2) > 0){
printf("S1 > S2\n");
} else{
printf("S1 < S2\n");
}
//8.定位操作
printf("***开始定位操作***\n");
if(Index(S1,Sub) != 0){
printf("子串Sub在S1中的位置为:%d\n", Index(S1,Sub));
} else{
printf("子串Sub不在S1中\n");
}
//9.一些其他函数的实现
printf("S1的长度为:%d\n",StrLength(S1));
ClearString(S1);
printf("S1的长度为:%d\n",StrLength(S1));
return 0;
}
参考来源:
数据结构代码参考博客
《王道数据结构》