串,包括KMP算法(C/C++)

#ifndef STRINGADT_H_
#define STRINGADT_H_
#include <stdbool.h>

#define FOLWOVER -1

struct StringADT;
typedef struct StringADT String;

struct StringADT
{
	char * ch;
	int length;
};

//为S开辟合适空间,储存输入的chars
void StrAssign(String &S, char * chars);
//利用S2覆盖S1
void StrCopy(String &S1, String &S2);
//串空返回true
bool StrIsEmpty(String &S); 
//若S1>S2,返回1,以此类推
int StringCompare(String &S1, String &S2);
//返回字符串的长度
int StrLength(String &S);
//清空串S
void ClearString(String &S);
//将S2接在S1后面,赋值给T
void StrConcat(String &T, String &S1, String &S2);
//将S第pos个字符起,共len个字符另外组成一个字符串赋值给Sub
void SubString(String &Sub, String &S, int pos, int len);
//KMP算法,从第pos个字符算起,若T是S的子串,返回T第一次出现的位置 
int Index(String &S, String &T, int pos);
//若T是S的子串,用V替代所有的T
void Replace(String &S, String &T, String &V);
//在串S的第pos个字符之前插入串T
void StrInsert(String &S, int pos, String &T);
//删除串S第pos个字符开始长度为len的字符串
void StrDelete(String &S, int pos, int len);
//打印出String,包括回车
void PrintfString(String &S);

#endif


#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "stringadt.h"

void StrAssign(String &S, char * chars)
{
	int i, lenChars = 0;//储存chars变量的长度 
	while (*chars != '\0'){ //计算长度 
		lenChars++;
		chars++;
	}

	S.ch = (char *)malloc(lenChars * sizeof(char));//为字符串分配内存,这里不多开辟一个空间给'\0'
	if (S.ch == NULL)								//是因为有length来替代'\0'指示字符串的结尾
		exit(FOLWOVER);

	chars = chars - lenChars; //指针指回字符串的第一个值
	S.length = lenChars;
	for (i = 0; i < lenChars; i++)
		S.ch[i] = chars[i];
}

void StrCopy(String &S1, String &S2)
{//用S2覆盖S1
	free(S1.ch);
	S1.ch = (char *)malloc(sizeof(char) * S2.length);
	for (int i = 0; i < S2.length; i++){
		S1.ch[i] = S2.ch[i];
	}
	S1.length = S2.length;
}

bool StrIsEmpty(String &S)
{
	if (S.length == 0)
		return true;
	else
		return false;
}

int StringCompare(String &S1, String &S2)
{
	int i = 0, result = 0;
	while (i < S1.length && i < S2.length){
		if (S1.ch[i] > S2.ch[i]){
			result = 1;
			break;
		}
		else if (S1.ch[i] < S2.ch[i]){
			result = -1;
			break;
		}
		else
			i++;
	}
	return result;
}

int StrLength(String &S)
{
	return S.length;
}

void ClearString(String &S)
{
	free(S.ch);//这样是删除,是删除所有字符
	S.length = 0;
}

void StrConcat(String &T, String &S1, String &S2)
{//将S2接在S1后面存在T中
	T.ch = (char *)malloc(sizeof(char) * (S1.length + S2.length));
	for (int i = 0; i < S1.length; i++){
		T.ch[i] = S1.ch[i];
	}
	for (int i = S1.length, j = 0; i < S2.length + S1.length; i++, j++){
		T.ch[i] = S2.ch[j];
	}
	T.length = S1.length + S2.length;
}

void SubString(String &Sub, String &S, int pos, int len)
{//将S第pos个字符起,共len个字符另外组成一个字符串赋值给Sub
	if (len + pos > S.length){
		printf("超过字符串长度!");
	}
	else{
		Sub.length = len;
		Sub.ch = (char *)malloc(sizeof(char) * len);
		for (int i = pos - 1, j = 0; i < pos + len - 1; i++, j++){
			Sub.ch[j] = S.ch[i];
		}
	}
}

void nextInit(String &T, int next[])//检测无误
{//next数组初始化,next[j]的值表示第0到j-1构成的字符串中最长的 前缀后缀相同 的长度
	int i = -1, j = 0;//i指向前缀,j指向后缀,
	next[0] = -1;//用-1标记递归结束点
	while (j < T.length - 1){
		if (i == -1 || T.ch[i] == T.ch[j]){//当前缀后缀匹配失败后,i = -1,next[j] = 0
			i++;						//当匹配成功,即T.ch[i] == T.ch[j],next[j] = i
			j++;//j指向后缀,不回溯
			next[j] = i;
		}
		else{
			i = next[i];//当i回溯到i = -1时,表示前缀后缀匹配失败
		}
	}
}

int Index(String &S, String &T, int pos)//验证无误
{//KMP算法,从第pos个字符算起,若T是S的子串,返回T第一次出现的位置(下标)
	int i = 0, j = pos - 1;//i指向模式串,j指向主串
	int * next;
	int index = -1;

	if (j + T.length > S.length - 1){
		return index;
	}

	next = (int *)malloc(sizeof(int) * T.length);
	nextInit(T, next);//初始化next数组

	while (j < S.length){
		if (i == -1 || T.ch[i] == S.ch[j]){
			if (i == T.length - 1){//匹配完毕,index赋值,退出
				index = j - i;
				break;
			}
			i++;
			j++;
		}
		else{
			i = next[i];
		}
	}
	return index;//匹配成功返回下标值,失败则返回-1
}

void Replace(String &S, String &T, String &V)
{//若T是S的子串,用V替代所有的T
	int tempIndex;//记录T出现时的下标
	tempIndex = Index(S, T, 1);
	if (tempIndex == -1){
		printf("不是子串!\n");
	}
	else{
		while (tempIndex != -1){
			StrDelete(S, tempIndex + 1, T.length);
			StrInsert(S, tempIndex + 1, V);
			tempIndex = Index(S, T, tempIndex + V.length + 1);
		}
	}
}

void StrInsert(String &S, int pos, String &T)//验证无误
{//在串S的第pos个字符之前插入串T
	S.ch = (char *)realloc(S.ch, S.length + T.length);
	for (int i = S.length - 1, j = T.length - 1; i >= pos - 1; i--, j--){
		S.ch[i + T.length] = S.ch[i];//S.ch[pos - 1]开始的数据右移,腾出空间
	}
	for (int i = pos - 1, j = 0; j < T.length; i++, j++){
		S.ch[i] = T.ch[j];//腾出的空间插入T.ch[]中的值
	}
	S.length = S.length + T.length;
}

void StrDelete(String &S, int pos, int len)//验证无误
{//删除串S第pos个字符开始长度为len的字符串 
	if (pos + len - 2 > S.length){
		printf("字符串下标越界!\n");
	}
	else{
		char * tempCharArray;
		tempCharArray = (char *)malloc(sizeof(char) * (S.length - len));
		for (int i = 0; i < pos - 1; i++){
			tempCharArray[i] = S.ch[i];
		}
		for (int i = pos + len - 1, j = pos - 1; i < S.length; i++, j++){
			tempCharArray[j] = S.ch[i];
		}
		free(S.ch);
		S.ch = tempCharArray;
		S.length = S.length - len;
	}
}

void PrintfString(String &S)
{//打印出String,输出完后不换行
	for (int i = 0; i < S.length; i++){
		printf("%c", S.ch[i]);
	}
	printf("\n");
}


#include <stdio.h>
#include <stdlib.h>
#include "stringadt.h"

int main()
{
	String testSS1;
	String testST1;
	String testSV1;

	StrAssign(testSS1, "qwer");
	StrAssign(testST1, "zxcvv");
	PrintfString(testSS1);
	PrintfString(testST1);

	StrCopy(testST1, testSS1);
	PrintfString(testST1);

	int x = StringCompare(testSS1, testST1);
	printf("x = %d\n", x);

	int length = StrLength(testSS1);
	printf("length = %d\n", length);

	StrConcat(testSV1, testSS1, testST1);
	PrintfString(testSV1);

	SubString(testSS1, testST1, 2, 2);
	PrintfString(testSS1);

	String testSS;
	String testST;
	String testSV;
	StrAssign(testSS, "qwerabaqwerqwerabab");
	StrAssign(testST, "abab");
	StrAssign(testSV, "AB");
	PrintfString(testSS);
	PrintfString(testST);
	PrintfString(testSV);

	//以下四选一轮流调试

	//Replace(testSS, testST, testSV);
	//PrintfString(testSS);

	//StrInsert(testST, 2, testSV);
	//PrintfString(testST);
	//printf("%d\n", testST.length);

	//StrDelete(testSS, 16, 4);
	//PrintfString(testSS);

	//int temp = Index(testSS, testST, 1);
	//printf("%d\n", temp);


	system("pause");
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值