串操作应用举例(文本编辑)

来源:互联网 发布:wav播放软件 编辑:程序博客网 时间:2024/06/05 16:19
// algo4-2.cpp 文本行编辑#include"c1.h"#include"c4-2.h" // 采用串的堆分配存储结构#include"bo4-2.cpp" // 串的堆分配基本操作#define MAX_LEN 25 // 文件最大行数#define LINE_LEN 75 // 每行字符数最大值+1#define NAME_LEN 20 // 文件名最大长度(包括盘符、路径)+1// 全局变量(见图4.12)HString T[MAX_LEN];char str[LINE_LEN],filename[NAME_LEN]="";FILE *fp;int n=0; // 文本行数void Open(){ // 打开文件(新或旧)if(filename[0]) // 文件已打开printf("已存在打开的文件\n");else{printf("请输入文件名(可包括盘符、路径,不超过%d个字符): ",NAME_LEN-1);scanf("%s",filename);fp=fopen(filename,"r"); // 以读的方式打开文件if(fp) // 已存在此文件{while(fgets(str,LINE_LEN,fp)) // 由文件读入1行字符成功{str[strlen(str)-1]=0; // 将换行符10强制改为串结束符0if(n>=MAX_LEN){printf("文件太大\n");return;}StrAssign(T[n],str);n++;}fclose(fp); // 关闭文件}elseprintf("新文件\n");}}void List(){ // 显示文本内容int i;for(i=0;i<n;i++){printf("%d: ",i+1);StrPrint(T[i]);}}void Insert(){ // 插入行int i,l,m;printf("在第l行前插m行,请输入l m: ");scanf("%d%d%*c",&l,&m);if(n+m>MAX_LEN){printf("插入行太多\n");return;}if(n>=l-1&&l>0){for(i=n-1;i>=l-1;i--)T[i+m]=T[i];n+=m;printf("请顺序输入待插入内容:\n");for(i=l-1;i<l-1+m;i++){gets(str);InitString(T[i]);StrAssign(T[i],str);}}elseprintf("行超出范围\n");}void Delete(){ // 删除行int i,l,m;printf("从第l行起删除m行,请输入l m: ");scanf("%d%d",&l,&m);if(n>=l+m-1&&l>0){for(i=l-1+m;i<n;i++){free(T[i-m].ch);T[i-m]=T[i];}for(i=n-m;i<n;i++)InitString(T[i]);n-=m;}elseprintf("行超出范围\n");}void Copy(){ // 拷贝行int i,l,m,k;printf("把第l行开始的m行插在原k行之前,请输入l m k: ");scanf("%d%d%d",&l,&m,&k);if(n+m>MAX_LEN){printf("拷贝行太多\n");return;}if(n>=k-1&&n>=l-1+m&&(k>=l+m||k<=l)){for(i=n-1;i>=k-1;i--)T[i+m]=T[i];n+=m;if(k<=l)l+=m;for(i=l-1;i<l-1+m;i++){InitString(T[i+k-l]);StrCopy(T[i+k-l],T[i]);}}elseprintf("行超出范围\n");}void Modify(){ // 修改行int i;printf("请输入待修改的行号: ");scanf("%d%*c",&i);if(i>0&&i<=n) // 行号合法{printf("%d: ",i);StrPrint(T[i-1]);printf("请输入新内容: ");gets(str);StrAssign(T[i-1],str);}elseprintf("行号超出范围\n");}void Search(){ // 查找字符串int i,k,f=1; // f为继续查找标志char b[2];HString s;printf("请输入待查找的字符串: ");scanf("%s%*c",str);InitString(s);StrAssign(s,str);for(i=0;i<n&&f;i++) // 逐行查找{k=1; // 由每行第1个字符起查找while(k){k=Index(T[i],s,k); // 由本行的第k个字符开始查找if(k) // 找到{printf("第%d行: ",i+1);StrPrint(T[i]);printf("第%d个字符处找到。继续查找吗(Y/N)? ",k);gets(b);if(b[0]!='Y'&&b[0]!='y') // 中断查找{f=0;break;}elsek++;}}}if(f)printf("没找到\n");}void Replace(){ // 替换字符串int i,k,f=1; // f为继续替换标志char b[2];HString s,t;printf("请输入待替换的字符串: ");scanf("%s%*c",str);InitString(s);StrAssign(s,str);printf("替换为");scanf("%s%*c",str);InitString(t);StrAssign(t,str);for(i=0;i<n&&f;i++) // 逐行查找、替换{k=1; // 由每行第1个字符起查找while(k){k=Index(T[i],s,k); // 由本行的第k个字符开始查找if(k) // 找到{printf("第%d行: ",i+1);StrPrint(T[i]);printf("第%d个字符处找到。是否替换(Y/N)? ",k);gets(b);if(b[0]== 'Y'||b[0]== 'y'){StrDelete(T[i],k,StrLength(s));StrInsert(T[i],k,t);}printf("继续替换吗(Y/N)?");gets(b);if(b[0]!= 'Y' &&b[0]!= 'y') // 中断查找、替换{f=0;break;}elsek+=StrLength(t);}}}if(f)printf("没找到\n");}void Save(){ // 存盘int i,j;fp=fopen(filename,"w"); // 以写的方式重新打开文件if(fp) // 打开文件成功{for(i=0;i<n;i++){ // 依次将每行存入文件for(j=0;j<T[i].length;j++) // 依次存入每个字符fputc(T[i].ch[j],fp);fputc(10,fp); // 存入换行符ClearString(T[i]); // 释放串空间}fclose(fp); // 关闭文件}elseprintf("存盘失败\n");}void main(){Status s=TRUE;int i,k;for(i=0;i<MAX_LEN;i++) // 初始化串InitString(T[i]);while(s){printf("请选择: 1.打开文件(新或旧) 2.显示文件内容\n");printf(" 3.插入行4.删除行5.拷贝行6.修改行\n");printf(" 7.查找字符串8.替换字符串\n");printf(" 9.存盘退出0.放弃编辑\n");scanf("%d",&k);switch(k){case 1: Open();break;case 2: List();break;case 3: Insert();break;case 4: Delete();break;case 5: Copy();break;case 6: Modify();break;case 7: Search();break;case 8: Replace();break;case 9: Save();case 0: s=FALSE;}}}

代码的运行结果:


algo4-3.cpp 是以教科书图4.9 为例建立书名关键词索引表的程序。教科书图4.9(a)
所示的书目文件存于BookInfo.txt 中,其内容如下:

005 Computer Data Structures
010 Introduction to Data Structures
023 Fundamentals of Data Structures
034 The Design and Analysis of Computer Algorithms
050 Introduction to Numerical Analysis
067 Numerical Analysis

程序首先将存于BookInfo.txt 文件中的每种书的书号及书名中的关键词提取出来。书
号存储于整型变量BookNo 中,书名中的每个关键词先临时存储于全局变量wdlist 中,
wdlist 的结构如图413 所示。
在提取书名的关键词时,要注意剔除the、a、of 等非索引词。这些词在书名中一般是
小写,对于首字母是小写的单词不作处理即可。但这些非索引词若是书名的第1 个单词,
则首字母也为大写。为了解决这个问题,将非索引词存入文件NoIdx.txt 中,内容如下:

5A
An
In
Of
The

NoIdx.txt 文件的内容可通过文字编辑软件自行输入。第1 行为非索引词个数,单词按
字典顺序排列。程序将文件NoIdx.txt 的内容读入全局变量noidx 中。noidx 的结构和
wdlist 相同,其内容如图414 所示。对于书名中的每个单词,首先检索是否出现在noidx
中,如果是,则不将该单词插入wdlist 中作为关键词。图413 在显示wdlist 结构的同时
也显示了wdlist 存储书目文件第4 本书(书号为34)时的内容。


程序依次根据临时存储于wdlist 中的每个书名的关键词,产生和充实关键词索引表。
方法是:首先建一个空的关键词索引表变量idxlist,然后依次查询wdlist 中的各个关键词
是否存在于idxlist 中。如果已存在,则仅把该关键词的书号按升序插入相应的链表中。否

则先按字母顺序将wdlist 中的关键词插入idxlist,再插入书号。idxlist 的结构及内容如图
415 所示。


书名关键词索引表仅在增加新书时有变化,因此不必在每次检索书名时都建立一次。
可以把algo4-3.cpp 生成的书名关键词索引表(idxlist)存成文件(BookIdx.txt),由索引查询
图书的程序algo4-4.cpp 调用。algo4-3.cpp 程序运行的结果就是生成BookIdx.txt 文件,
其内容如下:

9
Algorithms
1
34
Analysis
3
34 50 67
Computer

2

5 34

Data

3

5 10 23

Design
1
34
Fundamentals
1
23
Introduction
2
10 50
Numerical
2
50 67
Structures
3

5 10 23

// algo4-3.cpp 根据书目文件bookinfo.txt生成书名关键词索引文件bookidx.txt,// 为运行algo4-4.cpp做准备,算法4.9~4.14#include"c1.h"typedef int ElemType;#include"c2-5.h"#include"bo2-6.cpp"#include"c4-2.h"#include"bo4-2.cpp"#define MaxKeyNum 25 // 索引表的最大容量(关键词的最大数目)#define MaxLineLen 52 // 书目串(书目文件的1行)buf的最大长度#define MaxNoIdx 10 // 非索引词(也是一个书目中关键词)的最大数目struct WordListType // 一个书目的词表(顺序表)和非索引词表(有序表)共用类型{char *item[MaxNoIdx]; // 词表(字符串)指针数组int last; // 词的数量};struct IdxTermType // 索引项类型{HString key; // 关键词(堆分配类型,c4-2.h)LinkList bnolist; // 存放书号索引的链表(c2-5.h)};struct IdxListType // 索引表类型(有序表){IdxTermType item[MaxKeyNum+1]; // 索引项数组类型int last; // 关键词的个数};// 全局变量char buf[MaxLineLen+1]; // 当前书目串(包括’\0’)WordListType wdlist,noidx; // 暂存一种书的词表,非索引词表void InitIdxList(IdxListType &idxlist){ // 初始化操作,置索引表idxlist为空表,且在idxlist.item[0]设一空串idxlist.last=0;InitString(idxlist.item[0].key); // 初始化[0]单元,函数在bo4-2.cpp中InitList(idxlist.item[0].bnolist); // 初始化[0]单元,函数在bo2-6.cpp中}void ExtractKeyWord(int &BookNo){ // 从buf中提取书名关键词到词表wdlist,书号存入BookNoint i,l,f=1; // f是字符串buf结束标志0:结束1:未结束char *s1,*s2;for(i=1;i<=wdlist.last;i++){ // 释放上一个书目在词表wdlist的存储空间free(wdlist.item[i]);wdlist.item[i]=NULL;}wdlist.last=0; // 初始化词表wdlist的词数量BookNo=atoi(buf); // 将前几位数字转化为整数,赋给书号BookNos1=&buf[4]; // s1指向书名的首字符while(f){ // 提取书名关键词到词表wdlists2=strchr(s1,' '); // s2指向s1后的第一个空格,如没有,返回NULLif(!s2) // 到串尾(没空格){s2=strchr(s1,'\12'); // s2指向buf的最后一个字符(回车符10)f=0;}l=s2-s1; // 单词长度if(s1[0]>= 'A'&&s1[0]<='Z') // 单词首字母为大写{ // 写入词表wdlist.item[wdlist.last]=(char *)malloc((l+1)*sizeof(char)); // 生成串空间(包括'\0')for(i=0;i<l;i++)wdlist.item[wdlist.last][i]=s1[i]; // 写入词表wdlist.item[wdlist.last][l]=0; // 串结束符for(i=0;i<noidx.last&&(l=strcmp(wdlist.item[wdlist.last],noidx.item[i]))>0;i++);// 查找是否为非索引词if(!l) // 是非索引词{free(wdlist.item[wdlist.last]); // 从词表中删除该词wdlist.item[wdlist.last]=NULL;}elsewdlist.last++; // 词表长度+1}s1=s2+1; // s1移动到下一个单词的首字符处};}void GetWord(int i,HString &wd){ // 用wd返回词表wdlist中第i个关键词,算法4.11StrAssign(wd,wdlist.item[i]); // 生成关键字字符串bo4-2.cpp}int Locate(IdxListType &idxlist,HString wd,Status &b){ // 在索引表idxlist中查询是否存在与wd相等的关键词。若存在,则返回其// 在索引表中的位置,且b取值TRUE;否则返回插入位置,且b取值FALSE,算法4.12int i,m;for(i=idxlist.last;(m=StrCompare(idxlist.item[i].key,wd))>0;--i); // bo4-2.cppif(m==0) // 找到{b=TRUE;return i;}else{b=FALSE;return i+1;}}void InsertNewKey(IdxListType &idxlist,int i,HString wd){ // 在索引表idxlist的第i项上插入新关键词wd,并初始化书号索引的链表为空表,算法4.13int j;for(j=idxlist.last;j>=i;--j) // 后移索引项idxlist.item[j+1]=idxlist.item[j];InitString(idxlist.item[i].key); // bo4-2.cppStrCopy(idxlist.item[i].key,wd); // 串拷贝插入新的索引项bo4-2.cppInitList(idxlist.item[i].bnolist); // 初始化书号索引表为空表bo2-6.cppidxlist.last++;}void InsertBook(IdxListType &idxlist,int i,int bno){ // 在索引表idxlist的第i项中插入书号为bno的索引,算法4.14Link p;MakeNode(p,bno); // 分配结点bo2-6.cppp->next=NULL;Append(idxlist.item[i].bnolist,p); // 插入新的书号索引bo2-6.cpp}void InsIdxList(IdxListType &idxlist,int bno){ // 将书号为bno的关键词插入索引表,算法4.10int i,j;Status b;HString wd;InitString(wd); // bo4-2.cppfor(i=0;i<wdlist.last;i++){GetWord(i,wd);j=Locate(idxlist,wd,b); // 关键词的位置或待插入的位置(当索引表中不存在该词)if(!b) // 索引表中不存在关键词wdInsertNewKey(idxlist,j,wd); // 在索引表中插入新的索引项InsertBook(idxlist,j,bno); // 插入书号索引}}void PutText(FILE *f,IdxListType idxlist){ // 将生成的索引表idxlist输出到文件fint i,j;Link p;fprintf(f,"%d\n",idxlist.last);for(i=1;i<=idxlist.last;i++){for(j=0;j<idxlist.item[i].key.length;j++)fprintf(f,"%c",idxlist.item[i].key.ch[j]); // HString类型串尾没有\0,只能逐个字符输出fprintf(f,"\n%d\n",idxlist.item[i].bnolist.len);p=idxlist.item[i].bnolist.head;for(j=1;j<=idxlist.item[i].bnolist.len;j++){p=p->next;fprintf(f,"%d ",p->data);}fprintf(f,"\n");}}void main(){ // 算法4.9FILE *f; // 任何时间最多打开一个文件IdxListType idxlist; // 索引表int BookNo; // 书号变量int k;if(!(f=fopen("NoIdx.txt","r"))) // 打开非索引词文件exit(OVERFLOW);fscanf(f,"%d",&noidx.last); // 读取非索引词个数for(k=0;k<noidx.last;k++) // 把非索引词文件的内容依次拷到noidx中{fscanf(f,"%s",buf);noidx.item[k]=(char*)malloc((strlen(buf)+1)*sizeof(char));strcpy(noidx.item[k],buf);}fclose(f); // 关闭非索引词文件if(!(f=fopen("BookInfo.txt","r"))) // 打开书目文件exit(FALSE);InitIdxList(idxlist); // 设索引表idxlist为空,并初始化[0]单元while(fgets(buf,MaxLineLen,f)) // 由书目文件读取1行信息到buf成功{ExtractKeyWord(BookNo);//将buf中的书号存入BookNo,关键词提取到词表(当前书目的关键词表)中InsIdxList(idxlist,BookNo); // 将书号为BookNo的关键词及书号插入索引表idxlist中}fclose(f); // 关闭书目文件if(!(f=fopen("BookIdx.txt","w"))) // 打开书名关键词索引文件exit(INFEASIBLE);PutText(f,idxlist); // 将生成的索引表idxlist输出到书名关键词索引文件fclose(f); // 关闭书名关键词索引文件}

程序运行结果:生成BookIdx.txt 文件。
algo4-4.cpp 根据algo4-3.cpp 产生的文件BookIdx.txt 索引查询图书。首先将存有书
名关键词索引表信息的文件BookIdx.txt 的内容恢复到变量idxlist(见图415)中。为方便
查询,将关键词一律存为小写。再将书目文件BookInfo.txt 的内容存入到变量booklist(见
图416)中。程序运行时,从键盘输入一个书名关键词,并将此单词转为小写,在idxlist
中查找。如果找到,则根据相应的链表中所存储的书号,依次查询booklist 并输出相应的
书名。

// algo4-4.cpp 根据algo4-3.cpp产生的文件,索引查询图书#include"c1.h"typedef int ElemType;#include"c2-5.h"#include"bo2-6.cpp"#include"c4-2.h"#include"bo4-2.cpp"#define MaxBookNum 10// 假设只对10个书名建索引表#define MaxKeyNum 25// 索引表的最大容量(关键词的最大数目)#define MaxLineLen 46 // 书名的最大长度struct IdxTermType // 索引项类型{HString key; // 关键词(堆分配类型,c4-2.h)LinkList bnolist; // 存放书号索引的链表(c2-5.h)};struct IdxListType // 索引表类型(有序表){IdxTermType item[MaxKeyNum+1]; // 索引项数组类型int last; // 关键词的个数};struct BookTermType // 书目项类型{char bookname[MaxLineLen+1]; // 书名串(包括′\0′)int bookno; // 书号};struct BookListType // 书目表类型(有序表){BookTermType item[MaxBookNum]; // 书目项数组类型int last; // 书目的数量};void main(){FILE *f; // 任何时间最多打开一个文件IdxListType idxlist; // 索引表BookListType booklist; // 书目表char buf[MaxLineLen+5]; // 当前书目串(包括书号和’\0’)HString ch; // 索引字符串int BookNo; // 书号Link p; // 链表指针int i,j,k,flag=1; // flag是继续查询的标志InitString(ch); // 初始化HString类型的变量if(!(f=fopen("BookIdx.txt","r"))) // 打开书名关键词索引表文件exit(OVERFLOW);fscanf(f,"%d",&idxlist.last); // 书名关键词个数for(k=0;k<idxlist.last;k++) // 把关键词文件的内容拷到idxlist中{fscanf(f,"%s",buf);i=0;while(buf[i])buf[i++]=tolower(buf[i]); // 字母转为小写InitString(idxlist.item[k].key);StrAssign(idxlist.item[k].key,buf);InitList(idxlist.item[k].bnolist); // 初始化书号链表,bo2-6.cppfscanf(f,"%d",&i);for(j=0;j<i;j++){fscanf(f,"%d",&BookNo);MakeNode(p,BookNo); // 产生新的书号结点,bo2-6.cppp->next=NULL; // 给书号结点的指针域赋值Append(idxlist.item[k].bnolist,p); // 在表尾插入新的书号结点,bo2-6.cpp}}fclose(f);if(!(f=fopen("BookInfo.txt","r"))) // 打开书目文件exit(FALSE);i=0;while(fgets(buf,MaxLineLen,f)){ // 把书目文件的内容拷到booklist中booklist.item[i].bookno=atoi(buf); // 前几位数字为书号strcpy(booklist.item[i++].bookname,&buf[4]); // 将buf由书名开始的字符串拷贝到booklist中}booklist.last=i;while(flag){printf("请输入书目的关键词(一个):");scanf("%s",buf);i=0;while(buf[i])buf[i++]=tolower(buf[i]); // 字母转为小写StrAssign(ch,buf);i=0;do{k=StrCompare(ch,idxlist.item[i++].key); // bo4-2.cpp}while(k&&i<=idxlist.last);if(!k) // 索引表中有此关键词{p=idxlist.item[--i].bnolist.head->next; // p指向索引表中此关键词相应链表的首元结点while(p){j=0;while(j<booklist.last&&p->data!=booklist.item[j].bookno) //在booklist中找相应的书号j++;if(j<booklist.last)printf("%3d %s",booklist.item[j].bookno,booklist.item[j].bookname);p=p->next; // 继续向后找}}elseprintf("没找到\n");printf("继续查找请输入1,退出查找请输入0:");scanf("%d",&flag);}}

代码运行的结果:

请输入书目的关键词(一个):DATA
5 Computer Data Structures
10 Introduction to Data Structures
23 Fundamentals of Data Structures
继续查找请输入1,退出查找请输入0:1
请输入书目的关键词(一个):structure
没找到
继续查找请输入1,退出查找请输入0:0

0 0
原创粉丝点击