任务
静态存储一页文章,每行最多不超过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;
}
}
运行结果