一、实验目的:
(1)掌握串的顺序存储结构及定长字符串的基本操作。
(2)掌握串的BF和KMP模式匹配算法
二、实验原理
串是一种特殊的线性表,其特性体现在数据元素的一个字符,即串是一种内容受限的线性表。
定义:零个或者多个字符组成的有限序列。
子串:串中任意个连续的字符组成的子序列称为该串的字串。
主串:包含字串的串称为该字串的主串。
子串在主串中位置:字符在串中的序号称为该字符在串中的位置。
字符在主串中位置则以子串的第一个字符在主串中的位置表示。
串相等:两个串长度相等,且对应位置的字符也相等。
BF–蛮力算法(必须熟练掌握)
三、实验内容及步骤
1、建立顺序串结构。
2、输入串1和串2,在主函数中实现。输出串。
3、串的模式匹配。
4、串比较。比较串1和串2的大小,相等返回0,S1<S2返回-1,否则返回1.
5、串连接。把串2连接在串1的后面。输出串1。
6、串替换。输入串3,替换串1中包含的串2的所有内容。输出串1。
7、求子串。从串1中的第i个元素开始截取n个元素形成子串。输出子串。
四、实验源代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#define FALSE 0
#define TRUE 1#define MAXSIZE 50 /*初始分配的顺序串长度*/
typedef char ElemType; /*限定字符串元素值域必须为字符集*/typedef struct string {ElemType ch[MAXSIZE]; /*存储字符串的一维数组*/int length; /*字符串的实际长度,不包括结束符*/
}SString;SString* Create_SeqStr(char* s) /* 创建一个串,用字符串s初始化它 */
{int i;SString* pstr = (SString*)malloc(sizeof(SString)); /* 申请串空间 */if (pstr == NULL)printf("Out of space!!\n");else {pstr->length = 0;for (i = 0; *s != '\0'; i++) //把串s存储到字符串pstr中,并输出字符串{//printf("%c,",*s); pstr->ch[i] = *s++;//不会存‘\0’pstr->length++;}return pstr;}
}/*遍历顺序串s的所有字符*/
void Traverse_SString(SString* S) {int i;for (i = 0; i<S->length; i++)printf("%c", S->ch[i]);printf("\n");// return TRUE;
}/*TraverseList*//*1、串插入:在串S的第pos个字符处开始,插入串T*/
int SStrInsert(SString* S, int pos, const SString* T)
{int i;int j;if (NULL == S || NULL == S->ch || NULL == T || pos<0 || pos>S->length)return FALSE;if (T->length+S->length<=MAXSIZE)//判断两个串长相加后是否溢出{for (i = S->length - 1; i >=pos - 1; i--) //先把S串中插入位置后的字符,移动位置S->ch[i+T->length] = S->ch[i];for (i = 0; i < T->length; i++) //把串T插入到串S的第pos位S->ch[pos-1+i]=T->ch[i];S->length=S->length+T->length; //串S长度更新return TRUE;}elsereturn FALSE;
}/*2、串删除:从串S中删除从第pos个字符开始连续len个字符后形成的子串*/
int SStrDelete(SString* S, int pos, int len)
{int i;if (NULL == S || NULL == S->ch || len < 0 || pos<0 || pos>S->length - len)return FALSE;else{for(i=pos-1+len; i<S->length; i++) //挪动元素实现从第pos个字符开始删除len个字符S->ch[i-len]=S->ch[i];S->length=S->length-len;//串S长度更新return TRUE;}
}/*3、串连接:将串T的值连接在串S的后面*/
int SStrCat(SString* S, SString* T)
{int i;if (NULL == S || NULL == S->ch || NULL == T->ch)return FALSE;if (S->length+T->length<=MAXSIZE)//判断是否符合连接条件{for (i=0;i<T->length; i++)//把T中字符依次存入S中S->ch[(S->length)+i] = T->ch[i];S->length=S->length+T->length;//串长更新return TRUE;}elsereturn FALSE;
}/*4、求子串:截取串S中从第pos个字符开始连续len个字符形成的子串,并复制给串T*/
int SStrSub(SString* T, SString* S, int pos, int len)
{int i;if (NULL == S || NULL == S->ch || NULL == T || NULL == T->ch || len<0 || len>S->length - pos + 1 || pos<0 || pos>S->length)return FALSE;for (i = 0; i < len; i++)T->ch[i] = S->ch[pos-1 + i];T->length = len;//设置串T长度return TRUE;
}/*5、串比较:比较串S和串T的大小,S等于T返回0,S>T返回1,S<T返回-1*/
int SStrCompare(SString* S, SString* T)
{int i;if (NULL == S || NULL == S->ch || NULL == T || NULL == T->ch)printf("串S或串T不存在,不能比较!\n");else {for (i = 0;i<T->length&&i<S->length; i++) //S和T中对应位置字符依次比较//T,S的length谁大谁小不明确if (S->ch[i] != T->ch[i]) //判断比较是否进行break;if (i==T->length||i==S->length)//串S和串T相等return 0;if (S->ch[i]>T->ch[i])//串S>串Treturn 1;if (S->ch[i] < T->ch[i])//串S<串Treturn -1;}
}
/* 6、串匹配:蛮力(朴素)模式匹配算法:BF算法 */
/*在串S中第pos个字符处开始查找,串T是否存在,若存在,返回查找成功位序,否则返回FASLE*/
int SStrIndex_BF(SString* S, int pos, SString* T) {int i, j;if (NULL == S || NULL == S->ch || NULL == T || NULL == T->ch || pos<0 || pos>S->length)return FALSE;for (i=pos-1; i<S->length; i++)//设置查找区域{for (j = 0; j<T->length; j++) //从T中取出字符依次与S中字符比较 if (S->ch[i+j]!=T->ch[j]) //判断比较是否继续break;if (j==T->length)//查找成功,退出查找过程break;}if (j!=T->length)//查找失败或i==S->lengthreturn FALSE;elsereturn i + 1;
}/*7、串替换:在主串S中查找子串T,若找到并把子串T替换为子串V */
int SStrReplace(SString* S, SString* T, SString* V)
{int i, j;if (NULL == S || NULL == S->ch || NULL == T || NULL == T->ch || NULL == &V || NULL == V->ch)return FALSE;else for (i = 0; i < S->length; i++){j= SStrIndex_BF(S, i+1, T); //j用来存储,在串T中串S的位置if (j!=FALSE) //判断是否具有替换的条件{SStrDelete(S, j, T->length); //SStrDelete(SString *S, int pos, int len),在串S中删除串TSStrInsert(S, j, V); //SStrInsert(SString *S, int pos, const SString T),在串S中第j个位置开始插入串V}return TRUE;}
}int main() {int i, j;char str1[MAXSIZE];//=(char *)malloc(sizeof(char)*MAXSIZE) ;char* str2 = (char*)malloc(sizeof(char) * MAXSIZE);char* str3 = (char*)malloc(sizeof(char) * MAXSIZE);SString* StrS = (SString*)malloc(sizeof(SString));SString* StrT = (SString*)malloc(sizeof(SString));SString* StrV = (SString*)malloc(sizeof(SString));printf("\n ******************************************************************\n");printf("\n *********************** 顺 序 串 常 用 算 法 *********************\n");printf("\n ******************************************************************\n");printf("\n1、串插入:在串S的第pos个字符处插入串T\n");printf("请输入串S:");scanf("%s", str1);StrS = Create_SeqStr(str1);printf("请输入串T:");scanf("%s", str2);StrT = Create_SeqStr(str2);printf("请输入pos值:");scanf("%d", &i);if (SStrInsert(StrS, i, StrT)){printf("插入成功!\n遍历串S:");Traverse_SString(StrS);}elseprintf("插入失败!\n");printf("\n\n2、串删除:从串S中删除从第pos个字符开始连续len个字符后形成的子串\n");printf("请输入串S:");scanf("%s", str1);StrS = Create_SeqStr(str1);printf("请输入pos值:");scanf("%d", &i);printf("请输入len值:");scanf("%d", &j);if (SStrDelete(StrS, i, j)){printf("删除成功!\n遍历串S:");Traverse_SString(StrS);}elseprintf("删除失败!\n");printf("\n\n3、串连接:将串T的值连接在串S的后面\n");printf("请输入串S:");scanf("%s", str1);StrS = Create_SeqStr(str1);printf("请输入串T:");scanf("%s", str2);StrT = Create_SeqStr(str2);if (SStrCat(StrS, StrT)){printf("连接成功!\n遍历串S:");Traverse_SString(StrS);}elseprintf("连接失败!\n");printf("\n\n4、求子串:截取串S中从第pos个字符开始连续len个字符形成的子串,并复制给串T\n");printf("请输入串S:");scanf("%s", str1);StrS = Create_SeqStr(str1);StrT->length = 0;printf("请输入pos值:");scanf("%d", &i);printf("请输入len值:");scanf("%d", &j);if (SStrSub(StrT, StrS, i, j)){printf("求子串成功!\n遍历串T:");Traverse_SString(StrT);}elseprintf("求子串失败!\n");printf("\n\n5、串比较:比较串S和串T的大小,S等于T返回0,S>T返回1,S<T返回-1\n");printf("请输入串S:");scanf("%s", str1);StrS = Create_SeqStr(str1);printf("请输入串T:");scanf("%s", str2);StrT = Create_SeqStr(str2);if (SStrCompare(StrS, StrT) == 0){printf("串S等于串T\n");/*Traverse_SString(StrS);printf("等于");printf("串T:");Traverse_SString(StrT);*/}elseif (SStrCompare(StrS, StrT) == 1){printf("串S大于串T\n");/*Traverse_SString(StrS);printf("");printf(":");Traverse_SString(StrT);*/}else{printf("串S小于串T\n");/*Traverse_SString(StrS);printf("小于");printf("串T:");Traverse_SString(StrT);*/}printf("\n\n6、串匹配:蛮力(BF)模式匹配算法:\n");printf("在串S中第pos个字符处开始查找,串T是否存在,若存在,返回查找成功位序,否则返回FALSE\n");printf("请输入串S:");scanf("%s", str1);StrS = Create_SeqStr(str1);printf("请输入串T:");scanf("%s", str2);StrT = Create_SeqStr(str2);printf("请输入pos值:");scanf("%d", &i);if (SStrIndex_BF(StrS, i, StrT)){printf("匹配成功!\n返回串T在串S中位序:");printf(" %d\n", SStrIndex_BF(StrS, i, StrT));}elseprintf("匹配失败!\n");printf("\n\n7、串替换:在主串S中查找子串T,若找到并把子串T替换为子串V\n");printf("请输入串S:");scanf("%s", str1);StrS = Create_SeqStr(str1);printf("请输入串T:");scanf("%s", str2);StrT = Create_SeqStr(str2);printf("请输入串V:");scanf("%s", str3);StrV = Create_SeqStr(str3);if (SStrReplace(StrS, StrT, StrV)){printf("替换成功!\n遍历串S:");Traverse_SString(StrS);}elseprintf("插入失败!\n");}
五、实验结果
六、实验总结
1.串的结构体
typedef struct string {
ElemType ch[MAXSIZE];
int length;
}SString;
2.字符串的实际长度,不包括结束符,即串中不储存‘\0’,数组中每一个元素都为char型
3.这里的ElemType为char型
4.pos作为接口,指代第几个字符,返回的也是第几个字符(i+1),注意返回和使用的区别
5.串插入
for (i = S->length - 1; i >=pos - 1; i–) //先把S串中插入位置后的字符,移动T->length
S->ch[i+T->length] = S->ch[i];
for (i = 0; i < T->length; i++) //把串T插入到串S的第pos位
S->ch[pos-1+i]=T->ch[i];
6.串删除
for(i=pos-1+len; ilength; i++) //挪动元素实现从第pos个字符开始删除len个字符
T->ch[i-len]=S->ch[i];
7.插入删除等操作不能忘记更新length的值
8.串比较中T,S的length谁大谁小不明确,故两者的length均要考虑