C语言实现数据结构之文章编辑(KMP算法)

本文介绍了一个基于链式存储结构的程序,用于静态存储文章并实现统计英文字母、数字、空格数量,单词总数以及使用KMP算法查找和删除指定字符串的功能。
摘要由CSDN通过智能技术生成
任务

静态存储一页文章,每行最多不超过80个字符,共N行。统计文中所出现的英文字母的个数、数字的个数、空格的个数、总字数等。

分析

使用结构体存储文章,结构体成员包含每一行的字符串结点以及指向下一行结点的指针,采用链式存储。对于统计字符串使用KMP算法。

存储结构设计
typedef struct text { //
	char sline[90];
	struct text *next;
} TEXT;
源代码
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
#define N 100

typedef int bool;
#define true 1
#define false 0

int nextval[N];//存储nextval的值
int place[N];
int OverlayValue[N];
int num[4]= {0}; //num[0]代表空格 num[1]代表字母 num[2]代表数字 num[3]代表单词个数

typedef struct text { //
	char sline[90];
	struct text *next;
} TEXT;

bool isAlphabet(char t);//如果字符是字母就返回真
bool isDigit(char t);//如果是数字就返回真
bool isSpace(char t);//是空格就返回真
int wordnum(char *t);//统计某一行的单词数量
void GetNextval(char const *ptr,int plen,int *nextval); //求nextval
int kmp1(char const *scr,int slen,char const *ptr,int plen,int const *nextval,int pos);//求字符串中模式串的个数
int search(char const *scr,char const *ptr);///在主串中找到字串的位置,没有返回零
bool delet(char *scr,char const *ptr);//删除指定的字串。
bool readtext(TEXT *head,int n);//读入文章
void release(TEXT *head);//释放节点
void OutputText(TEXT *head);//在屏幕上输出文字
int countword(TEXT *head,char const *ptr);//统计文章中某个单词的个数
void countother(TEXT *head);//统计文章中的空格,字母,数字和单词的个数
int deltext(TEXT *head,char const *ptr,int *OverlayValue);//删除文章中的指定单词
void OverlayFun(char const *ptr,int *OverlayValue);//覆盖函数

int main() {
	TEXT *head;
	head=(TEXT *)malloc(sizeof(TEXT));
	if(head==NULL) {
		printf("内存分配失败\n");
		return -1;
	}
	printf("请输入你要写入的文章的行数: ");
	int n;
	scanf("%d",&n);
	getchar();
	readtext(head,n);
	
	int code;
	printf("--------------------文章编辑系统----------------------\n");
	printf(" | 1.统计文章英文字母数、空格数及总字数                |\n");
	printf("------------------------------------------------------\n");
	printf(" | 2.统计某一字符串在文章中出现的次数                  |\n");
	printf("------------------------------------------------------\n");
	printf(" | 3.删除某一字符串                                    |\n");
	printf("------------------------------------------------------\n");
	printf(" | 0.退出系统                                          |\n");
	printf("------------------------------------------------------\n");
	while(1) {
		printf("\n请选择操作:"); 
		scanf("%d", &code);
		switch(code) {
			case 1: countother(head);
					printf("文章中英文字母数:%d\n空格数:%d\n总字数:%d\n",num[1],num[0],num[0]+num[1]+num[2]);
					break;  
			case 2: printf("请输入你要查找的字符串: ");
					char t[80];
					scanf("%s",t);
					GetNextval(t,strlen(t),nextval);
					int thewordnum=countword(head,t);
					printf("你查找的字符串在文章中的个数是:%d\n",thewordnum);
					break;  
			case 3: printf("请输入你要删除的单词:");
					char thedel[80];
					scanf("%s",thedel);
					deltext(head,thedel,OverlayValue);
					printf("输出删除后的文章\n");
					OutputText(head);
					break;
			case 0: printf("谢谢使用!\n");
					release(head);
				    return 0;  
			default: printf("暂不支持该功能!\n");
				     break;
		}
		fflush(stdin);			//清空键盘缓冲区
	}

	
}
bool isAlphabet(char t) { //如果字符是字母就返回真
	if(t>='a'&&t<='z' || t>='A'&&t<='Z')
		return true;
	else return false;
}
bool isDigit(char t) { //如果是数字就返回真
	if(t>='0' && t<='9')
		return true;
	else return false;
}
bool isSpace(char t) { //是空格就返回真
	if(t==' ')
		return true;
	else return false;
}
int wordnum(char *t) { //统计字符串中的单词个数
	int i;
	bool tag=false;
	bool is=false;
	int wordnum=0;
	for(i=0; i<strlen(t); i++) {
		if(t[i]==' ' && !tag)//忽略字符串开头的空格字符
			continue;
		else tag=true;

		if(t[i]>='a' && t[i]<='z' || t[i]>='A' && t[i]<='Z') {
			is=true;
		} else if((t[i]==' ' || t[i]==',' || t[i]=='.' || t[i]=='\n'|| t[i]=='\0' || t[i]=='?' || t[i]=='!')  && is) { //is为true代表在遇到空格或其他分隔符之前遇到字母
			wordnum++;
			is=false;
		}
	}
	if(is)wordnum++;
	return wordnum;
}

void GetNextval(char const *ptr,int plen,int *nextval) { //求nextval
	int i=0;
	nextval[0]=-1;
	int j=-1;
	while(i<plen-1) {
		if(j==-1 || ptr[j]==ptr[i]) {
			j++;
			i++;
			if(ptr[i]==ptr[j])
				nextval[i]=j;
			else
				nextval[i]=nextval[j];
		} else
			j=nextval[j];
	}
}
// scr 为指向主串的指针,ptr为指向模式串的指针
int kmp1(char const *scr,int slen,char const *ptr,int plen,int const *nextval,int pos) {
	int count=0;//统计字符串中模式串的个数
	int i=pos;
	int j=0;
//	while(i<slen && j<plen)
	while(i<slen) {
		if(j==-1 || scr[i]==ptr[j]) {
			i++;
			j++;
			if(j==plen) {
				count++;
				j=0;
			}
		} else  j=nextval[j];
	}
//	if(j>=plen)
//		return i-plen;
//	else return -1;
	return count;
}

void OverlayFun(char const *ptr,int *OverlayValue) {
	int plen=strlen(ptr);
	OverlayValue[0]=-1;
	int i,index=0;
	for(i=1; i<plen; i++) {
		index=OverlayValue[i-1];
		while(index>=0 && OverlayValue[i]!=OverlayValue[index+1]) {
			index=OverlayValue[index];
		}
		if(OverlayValue[i]==OverlayValue[index+1])
			OverlayValue[i]=index+1;
		else OverlayValue[i]=-1;
	}
}
int search(char const *scr,char const *ptr) {
	int slen=strlen(scr);
	int plen=strlen(ptr);
	memset(place,-1,sizeof(place));
	int pindex=0,sindex=0;
	int t=0;
	while(sindex<slen) {
		if(scr[sindex]==ptr[pindex]) {
			sindex++;
			pindex++;
			if(pindex==plen) {

				place[t++]=sindex-pindex;
				//pindex=0;
			}
		} else if(pindex==0)
			sindex++;
		else pindex=OverlayValue[pindex-1]+1;
	}
	return t;
}
bool delet(char *scr,char const *ptr) {
	int len=search(scr,ptr);
	int plen=strlen(ptr);
	int slen=strlen(scr);
	int sum=0;
	char temp[80];
	if(len==0) { //在主串中没有找到模式串
		return false;
	}
	int j=0,r=0;
	for(int i=0; i<slen; i++) {
		if(i==place[j]) {
			j++;
			i=i+plen-1;
			continue;
		}
		temp[r++]=scr[i];
	}
	temp[r]='\0';
	strcpy(scr,temp);
	return true;
}
int  deltext(TEXT *head,char const *ptr,int *OverlayValue) {
	OverlayFun(ptr,OverlayValue);
	TEXT *p=head->next;
	int tag=0;
	while(p) {
		if(!delet(p->sline, ptr)) {
			//	printf("无法删除");
			//	exit(0);
			tag++;
		}
		p=p->next;
	}
	return tag;
}
bool readtext(TEXT *head,int n) {

	if(n<=0) return false;
	TEXT *p=head;

	printf("请输入你的文章,每行不超过80个字符\n");
	while(n--) {
		char temp[80];
		gets(temp);
		TEXT *s=(TEXT *)malloc(sizeof(TEXT));
		if(s==NULL)return false;
		strcpy(s->sline,temp);
		s->next=NULL;
		p->next=s;
		p=s;
	}
	return true;
}
void release(TEXT *head) {
	TEXT *p=head,*q;
	while(p) {
		q=p->next;
		free(p);
		p=q;
	}
}

void OutputText(TEXT *head) {
	TEXT *p=head->next;
	while(p) {
		printf("%s\n",p->sline);
		p=p->next;
	}
}

int countword(TEXT *head,char const *ptr) {
	int count=0;
	TEXT *p=head->next;
	while(p) {
		count+=kmp1(p->sline,strlen(p->sline),ptr,strlen(ptr),nextval,0);
		p=p->next;
	}
	return count;
}

void countother(TEXT *head) {
	TEXT *p=head->next;
	int i;
	while(p) {
		for(i=0; i<strlen(p->sline); i++) {
			if(isAlphabet(p->sline[i]))
				num[1]++;
			if(isSpace(p->sline[i]))
				num[0]++;
			if(isDigit(p->sline[i]))
				num[2]++;
		}
		num[3]+=wordnum(p->sline);
		p=p->next;
	}
}
运行结果

 

  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种字符串匹配算法,可以在一个主串中查找一个模式串是否出现。这里提供一个用C语言实现KMP算法。 首先,需要定义一个函数`get_next`,用于计算模式串的next数组。next数组是一个长度为模式串长度的整型数组,表示当匹配失败时,模式串应该向右移动的位数。 ```c void get_next(char* pattern, int* next) { int i = 0, j = -1; next[0] = -1; while (i < strlen(pattern)) { if (j == -1 || pattern[i] == pattern[j]) { i++; j++; next[i] = j; } else { j = next[j]; } } } ``` 接下来,定义一个函数`kmp`,用于在主串中查找模式串。函数的参数包括主串指针、主串长度、模式串指针、模式串长度和next数组。 ```c int kmp(char* text, int text_len, char* pattern, int pattern_len, int* next) { int i = 0, j = 0; while (i < text_len && j < pattern_len) { if (j == -1 || text[i] == pattern[j]) { i++; j++; } else { j = next[j]; } } if (j == pattern_len) { return i - j; } else { return -1; } } ``` 下面是一个完整的示例代码: ```c #include <stdio.h> #include <string.h> void get_next(char* pattern, int* next) { int i = 0, j = -1; next[0] = -1; while (i < strlen(pattern)) { if (j == -1 || pattern[i] == pattern[j]) { i++; j++; next[i] = j; } else { j = next[j]; } } } int kmp(char* text, int text_len, char* pattern, int pattern_len, int* next) { int i = 0, j = 0; while (i < text_len && j < pattern_len) { if (j == -1 || text[i] == pattern[j]) { i++; j++; } else { j = next[j]; } } if (j == pattern_len) { return i - j; } else { return -1; } } int main() { char text[] = "ABABABABCABAAB"; char pattern[] = "ABABCABAA"; int text_len = strlen(text); int pattern_len = strlen(pattern); int next[pattern_len]; get_next(pattern, next); int pos = kmp(text, text_len, pattern, pattern_len, next); if (pos == -1) { printf("Pattern not found.\n"); } else { printf("Pattern found at position %d.\n", pos); } return 0; } ``` 输出结果为: ``` Pattern found at position 6. ``` 表示在主串中找到了模式串,并且位置为6。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值