任务
静态存储一页文章,每行最多不超过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("内存分配失败 "); return -1; } printf("请输入你要写入的文章的行数: "); int n; scanf("%d",&n); getchar(); readtext(head,n); int code; printf("--------------------文章编辑系统---------------------- "); printf(" | 1.统计文章英文字母数、空格数及总字数 | "); printf("------------------------------------------------------ "); printf(" | 2.统计某一字符串在文章中出现的次数 | "); printf("------------------------------------------------------ "); printf(" | 3.删除某一字符串 | "); printf("------------------------------------------------------ "); printf(" | 0.退出系统 | "); printf("------------------------------------------------------ "); while(1) { printf(" 请选择操作:"); scanf("%d", &code); switch(code) { case 1: countother(head); printf("文章中英文字母数:%d 空格数:%d 总字数:%d ",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 ",thewordnum); break; case 3: printf("请输入你要删除的单词:"); char thedel[80]; scanf("%s",thedel); deltext(head,thedel,OverlayValue); printf("输出删除后的文章 "); OutputText(head); break; case 0: printf("谢谢使用! "); release(head); return 0; default: printf("暂不支持该功能! "); 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]==' '|| t[i]==' ' || 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]=' '; 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个字符 "); 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 ",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; } }
运行结果