串及其应用

  • Post author:
  • Post category:其他


一、实验目的:

(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;
	}
	else
		return 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;
	}
	else
		return 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>串T
			return 1;
		if (S->ch[i] < T->ch[i])//串S<串T
			return -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->length
		return FALSE;
	else
		return  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中删除串T
				SStrInsert(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);
		}
		else
			printf("插入失败!\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);
		}
		else
			printf("删除失败!\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);
		}
		else
			printf("连接失败!\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);
		}
		else
			printf("求子串失败!\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);*/
		}
		else
			if (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));
		}
		else
			printf("匹配失败!\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);
		}
		else
			printf("插入失败!\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均要考虑



版权声明:本文为m0_63949203原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。