摘 要
本次课程设计是利用我们数据结构这门课程中所学习的线性表及与其相关的一些知识所完成的。通过使用双向链表来实现文章编辑的各项功能。文章编辑需要统计文章中的所有文字信息,需要分行显示,涉及到很多方面的知识,要使用链表来存储文章。文章编辑程序的主要功能是统计文章中的全部字母数、数字个数、空格个数和文章总字数,并且能准确的查找、删除字符串。主要应用的函数和语句有循环,查找,删除等。由程序开始运行后进行字符串的录入之后进行字符的输出,然后是利用循环和查找,进行字符的统计并输出已经找到的字符(包括字母、数字、空格)出现的次数以及总共的字符数。在这些运行完之后,根据要求还有一项功能--删除,对指定的字符进 行删除,同样,这里也需应用到循环,查找和删除。
关键词:C++、线性表、文章编辑
目 录
1 系统功能概述 ........................................ 错误!未定义书签。
1.1合同管理系统功能分析 ............................ 错误!未定义书签。 1.2 系统结构图 ..................................... 错误!未定义书签。 2 数据库设计 .......................................... 错误!未定义书签。
2.1需求分析 ........................................ 错误!未定义书签。 2.2 E-R模型 ........................................ 错误!未定义书签。 2.3关系模型 ........................................ 错误!未定义书签。 2.4表结构设计 ...................................... 错误!未定义书签。 3.1用户登录 ........................................ 错误!未定义书签。 3.2主窗体界面 ...................................... 错误!未定义书签。 3.3添加修改删除页面 ................................ 错误!未定义书签。 3.4查询页面 ........................................ 错误!未定义书签。 3.5注册新用户 ...................................... 错误!未定义书签。 4 课设总结 ............................................. 错误!未定义书签。 参考文献 ............................................... 错误!未定义书签。
一. 本课程设计的目的和任务
1.提高对数据逻辑结构的特点以及存储表示方式的认识,培养在具体应用中选择合适的数据结构和存储结构的能力。
2.熟悉软件开发的基本过程,初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等阶段基本任务和技能方法。
3.培养自己的算法设计和算法分析能力,提高综合运用所学的理论知识和方法独立分析和解决问题的能力。
4.训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的工作方法、作风和相互合作的精神。
5.综合运用链表的查找、插入和删除,理论结合实际,将其运用到文章编辑这一实验中。使这些知识得到进一步巩固、加深和拓展。利用模块的思想,模块之间用指针连接,减少了不必要的麻烦。巩固加深指针的用途,理解模块的优点。加深对链表的理解,全面认识链表操作的字符串的模式匹配操作。
二、 系统设计
2.1. 输入模块
存储结构:采用单链表结构存储文章,每个结点存储一行,每行最长不超过80个字符。
结构定义:
typedef struct line{
char *data; //字符串指针需要时动态分配内存 struct line *next; }LINE;
算法描述:用gets 函数接收输入,每遇到一个回车换行就新建一个结点,将当前行存入其data 域。当发现输入为^E时,在Data 的最后加上字符串结束标志,并置当前结点的Next 指针域为NULL 。
2.2. 统计模块
统计模块包括统计全部字母数,统计数字个数,统计空格个数,以及统计文章总字数,这四个部分的实现算法大体相同,四者的关系是:全部字母数+数字个数+空格个数=文章总字数,也就是说可以在统计出其中三者的前提下计算出第四个的数量。
另外一个重要的统计功能是统计某一字符串在整篇文章中出现的次数,这个需要用到串的模式匹配算法来实现。
2.3. 删除模块
删除模块的算法思想类同统计字符串的算法思想,由于采用了链表的存储结构,使得删除算法的时间复杂度大大减少。
void Del_String(LINE * &head,char *sch){ //删除指定的字符串 LINE *p=head; do {
while(strstr(p->data,sch)!=NULL)del_string_word(p->data,sch); } while((p=p->next)!=NULL); //遍历链表
2.4、程序结构图
图 2.5程序设计流程图
三、源程序清单 #include #include #include #include #include typedef struct line{
char *data; //字符串指针需要时动态分配内存 struct line *next; }LINE;
void CreateTXT(LINE * &head); //创建一张列表,同时向里面输入文本数据 int Count_Space(LINE * &head); //统计空格数 int Count_ZM(LINE * &head); // 统计字母数
int Count_All_Word(LINE * &head); //统计文章的总字数
int Find_Word(LINE * &head,char *sch); //统计sch 在文章中出现的次数 int Count_Num(LINE * &head); //统计数字数
void Del_String(LINE * &head,char *sch); //删除指定的字符串 void OutPutTxt(LINE * &head); //向屏幕输出文章 void Tj(LINE * &head); //统计 int read_text(LINE * &head); int free_link(LINE *&head);
int free_link(LINE *&head)
{
LINE *p=head; do
{ p->data=NULL; }
while((p=p->next)!=NULL); head->next=NULL; return 0; }
void setcolor(unsigned short color) { }
void CreateTXT(LINE * &head){
LINE *p=new LINE; //首先为链表 建立一个附加表头结点 head=p; //将p 付给 表头指针 char tmp[80]; while(1) {
gets(tmp); //输入字符串!使用C 的输入函数
if(tmp[0]==5)break; //如果发现输入 ^E,则退出输入 p->data=new char[strlen(tmp)+1];//为结点分配空间 strcpy(p->data,tmp);
if(tmp[strlen(tmp)-1]==5){ //除去最后一个控制符 ^E
free(p->data);
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hCon,color);
p->data[strlen(tmp)-1]='\0'; break; } }
p->next=NULL; //是最后的一个指针为空。 head=head->next; }
int Count_Space(LINE * &head){ //统计空格数 LINE *p=head;
int asc_space=32; //空格的ASCIC 码值 int count=0; do {
int Len=strlen(p->data); //计算当前 data 里的数据元素的个数
for(int i=0;i
if(p->data[i]==asc_space)count++; //计算空格数 }
while((p=p->next)!=NULL); //遍历链表 return count; }
int Count_Num(LINE * &head){ //统计数字数 LINE *p=head; int count=0; do {
int Len=strlen(p->data); //计算当前 data 里的数据元素的个数
for(int i=0;i
if(p->data[i]>=48 && p->data[i]
while((p=p->next)!=NULL); //遍历链表 return count; }
int Count_ZM(LINE * &head){ // 统计字母数
int count=Count_All_Word(head); //总的字符数,包含空格 int space_count=Count_Space(head); //空格数 int num_count=Count_Num(head);//数字数
return count-space_count-num_count; //返回文章的字母总数 }
int Count_All_Word(LINE * &head){ //统计文章的总字数 LINE *p=head; //保存链表的首地址 int count=0; //总字母数 do
{count+=strlen(p->data);} //计算当前行内的字符数 while((p=p->next)!=NULL); //遍历链表 return count; }
int Find_Word(LINE * &head,char *sch){ //统计 sch 在文章中出现的次数 LINE *p=head; int count=0; // int h=0;
int len1=0; //保存当前行的总字符数 int len2=strlen(sch); //待统计字符串的长度 int i,j,k; do {
len1=strlen(p->data);//当前行的字符数
for(i=0;i
if(p->data[i]==sch[0]) { k=0;
for(j=0;j
if(p->data[i+j]==sch[j])k=k+1; if(k==len2){count++;i=i+k-1;} } } }
while((p=p->next)!=NULL); //遍历链表 return count; }
void del_string_word(char *s,char *sch) {
// *s为输入的字符串 // *sch 为将要删除的字符
char *p=strstr(s,sch); //查询结果 char tmp[80]; int len=strlen(s); int i=len-strlen(p); int j=i+strlen(sch); int count=0;
for(int k=0;k
strcpy(s,tmp); //返回新的字符串
}
void Del_String(LINE * &head,char *sch){ //删除指定的字符串 LINE *p=head; do {
while(strstr(p->data,sch)!=NULL)del_string_word(p->data,sch); } while((p=p->next)!=NULL); //遍历链表 }
void OutPutTxt(LINE * &head){ //向屏幕输出文章 LINE *p=head; do
{ coutdata
} while((p=p->next)!=NULL); //遍历 链表 }
void Tj(LINE * &head){ //统计
cout
void main() {
setcolor(10); LINE *head; int opt;
cout
cout>opt; if(opt!=1)
{cout
// int n;int i;ElemType e; while(opt!=6){ //
switch (opt) { case 0:{
cout
cout
请选择操作
请选择操作
cin>>opt;
if (opt!=1&&opt!=2&&opt!=3&&opt!=4&&opt!=5&&opt!=6) {cout
case 1:{cout
cout
cout
case 2:{cout
setcolor(14);OutPutTxt(head);setcolor(10);cout
cout
case 3:{cout
cout
case 4:{cout
gets(sch);
}
cout
cout
setcolor(10);
cout
case 5:{cout
setcolor(14);
cout>tmp_sch;
gets(tmp_sch);
Del_String(head,tmp_sch); //删除指定字符
cout
OutPutTxt(head); //向屏幕输出 文章
setcolor(10);
cout
cout
cout
free_link(head);//释放链表空间 }//end of while }//end of else }
}
四、调试过程的系统测试情况及问题 4.1测试情况
程序运行,首先显示选择菜单,如图示:
选择1, 输入文章,界面运行结果如下:
按回车,调出开始菜单,输入2, 选择浏览,可以原样显示出刚才输入的文本:
回车后输入3,可以看到文章统计信息结果:
根据页面提示,回车
统计字符串模块,输入要统计的字符串,可以查找出该字符串在文章中出现过的次数。运行情况如下图示:
根据页面提示,回车
删除模块,输入要删除的字符串,执行删除后可以显示删除后的文本。界面如下:
根据页面提示,回车:
退出页面,执行后的结果如下:
4.2问题
①主流程进入死循环。.
②解决方案:每个循环都加break ,每跳出一个模块,opt 重新赋值为0。 输入多个变量,需要空格间隔时,程序只读空格前的变量
解决方案:输. 入函数用get( )函数,形式为:get(tmp),即可解决着个问题。 ③不识别自定义函数。
解决方案:函数定义前要函数声明,若不声明,则调用函数必须在函数定义之后,否则不识别。
④程序结束之后,链表仍占空间。
解决方案:在建立链表是所申请的内存空间在程序结束之前用free_link(LINE *&head)函数释放,即删除链表中的全部结点,且将链表头指针置为空。 4.3 注意事项:
① opt代表选项(共六个,多于六个显示“不可识别选项”)。
②建立文章,用链表存储,p=p->next=new LINE,即文章的每一行存储在一个结点中。 ③Ctrl+E为结束标志。 ④了解常用AS Ⅱ码。
课设总结
本实验采用链式顺序表结构实现了文章编辑的基本功能,实验过程中遇到了很多或大或小的问题,在这些问题的解决过程中,加深了对链表的理解,使我对链表操作的字符串的模
式匹配有了更深更全面的认识。
本实验提高了我对数据逻辑结构的特点和存储表示方式的认识,培养了我在具体应用中选择合适的数据结构和存储结构的能力。
通过该实验,使我熟悉了软件开发的基本过程,初步掌握了软件开发过程的问题分析、系统设计、程序编码测试等阶段的基本任务和技能方法。
使我的算法设计和算法分析能力以及运用所学理论知识和方法独立分析问题的能力得到全面的提高。
训练了我用系统的观点和软件开发的一般规范。使我认识到一个软件工作者所应该具备的科学的工作方法、作风和相互合作精神。
本实验的模块化比较强,各个模块之间用指针head 连接。认清模块化的概念给程序的顺利编制起到了很大的作用。分模块各个调试,可以减少很多不必要的麻烦。
参考文献
1] 耿国华等编著,数决结构—C 语言描述(第二版) ,西安电子科 技大学出版社,2008.7 [2] 赵文静, 祁飞等编著,数据结构与算法,科学出版社,2005.08
[3] 赵文静编著,数据结构-C++语言描述,西安交通大学出版社, 1999.01 [4] 孙鑫, 于安萍编著,VC++深入详解,电子工业出版社,2007.7
[5] COHOON & DAVIDSON 编著,C++程序设计,清华大学出版社, 2005.8
摘 要
本次课程设计是利用我们数据结构这门课程中所学习的线性表及与其相关的一些知识所完成的。通过使用双向链表来实现文章编辑的各项功能。文章编辑需要统计文章中的所有文字信息,需要分行显示,涉及到很多方面的知识,要使用链表来存储文章。文章编辑程序的主要功能是统计文章中的全部字母数、数字个数、空格个数和文章总字数,并且能准确的查找、删除字符串。主要应用的函数和语句有循环,查找,删除等。由程序开始运行后进行字符串的录入之后进行字符的输出,然后是利用循环和查找,进行字符的统计并输出已经找到的字符(包括字母、数字、空格)出现的次数以及总共的字符数。在这些运行完之后,根据要求还有一项功能--删除,对指定的字符进 行删除,同样,这里也需应用到循环,查找和删除。
关键词:C++、线性表、文章编辑
目 录
1 系统功能概述 ........................................ 错误!未定义书签。
1.1合同管理系统功能分析 ............................ 错误!未定义书签。 1.2 系统结构图 ..................................... 错误!未定义书签。 2 数据库设计 .......................................... 错误!未定义书签。
2.1需求分析 ........................................ 错误!未定义书签。 2.2 E-R模型 ........................................ 错误!未定义书签。 2.3关系模型 ........................................ 错误!未定义书签。 2.4表结构设计 ...................................... 错误!未定义书签。 3.1用户登录 ........................................ 错误!未定义书签。 3.2主窗体界面 ...................................... 错误!未定义书签。 3.3添加修改删除页面 ................................ 错误!未定义书签。 3.4查询页面 ........................................ 错误!未定义书签。 3.5注册新用户 ...................................... 错误!未定义书签。 4 课设总结 ............................................. 错误!未定义书签。 参考文献 ............................................... 错误!未定义书签。
一. 本课程设计的目的和任务
1.提高对数据逻辑结构的特点以及存储表示方式的认识,培养在具体应用中选择合适的数据结构和存储结构的能力。
2.熟悉软件开发的基本过程,初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等阶段基本任务和技能方法。
3.培养自己的算法设计和算法分析能力,提高综合运用所学的理论知识和方法独立分析和解决问题的能力。
4.训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的工作方法、作风和相互合作的精神。
5.综合运用链表的查找、插入和删除,理论结合实际,将其运用到文章编辑这一实验中。使这些知识得到进一步巩固、加深和拓展。利用模块的思想,模块之间用指针连接,减少了不必要的麻烦。巩固加深指针的用途,理解模块的优点。加深对链表的理解,全面认识链表操作的字符串的模式匹配操作。
二、 系统设计
2.1. 输入模块
存储结构:采用单链表结构存储文章,每个结点存储一行,每行最长不超过80个字符。
结构定义:
typedef struct line{
char *data; //字符串指针需要时动态分配内存 struct line *next; }LINE;
算法描述:用gets 函数接收输入,每遇到一个回车换行就新建一个结点,将当前行存入其data 域。当发现输入为^E时,在Data 的最后加上字符串结束标志,并置当前结点的Next 指针域为NULL 。
2.2. 统计模块
统计模块包括统计全部字母数,统计数字个数,统计空格个数,以及统计文章总字数,这四个部分的实现算法大体相同,四者的关系是:全部字母数+数字个数+空格个数=文章总字数,也就是说可以在统计出其中三者的前提下计算出第四个的数量。
另外一个重要的统计功能是统计某一字符串在整篇文章中出现的次数,这个需要用到串的模式匹配算法来实现。
2.3. 删除模块
删除模块的算法思想类同统计字符串的算法思想,由于采用了链表的存储结构,使得删除算法的时间复杂度大大减少。
void Del_String(LINE * &head,char *sch){ //删除指定的字符串 LINE *p=head; do {
while(strstr(p->data,sch)!=NULL)del_string_word(p->data,sch); } while((p=p->next)!=NULL); //遍历链表
2.4、程序结构图
图 2.5程序设计流程图
三、源程序清单 #include #include #include #include #include typedef struct line{
char *data; //字符串指针需要时动态分配内存 struct line *next; }LINE;
void CreateTXT(LINE * &head); //创建一张列表,同时向里面输入文本数据 int Count_Space(LINE * &head); //统计空格数 int Count_ZM(LINE * &head); // 统计字母数
int Count_All_Word(LINE * &head); //统计文章的总字数
int Find_Word(LINE * &head,char *sch); //统计sch 在文章中出现的次数 int Count_Num(LINE * &head); //统计数字数
void Del_String(LINE * &head,char *sch); //删除指定的字符串 void OutPutTxt(LINE * &head); //向屏幕输出文章 void Tj(LINE * &head); //统计 int read_text(LINE * &head); int free_link(LINE *&head);
int free_link(LINE *&head)
{
LINE *p=head; do
{ p->data=NULL; }
while((p=p->next)!=NULL); head->next=NULL; return 0; }
void setcolor(unsigned short color) { }
void CreateTXT(LINE * &head){
LINE *p=new LINE; //首先为链表 建立一个附加表头结点 head=p; //将p 付给 表头指针 char tmp[80]; while(1) {
gets(tmp); //输入字符串!使用C 的输入函数
if(tmp[0]==5)break; //如果发现输入 ^E,则退出输入 p->data=new char[strlen(tmp)+1];//为结点分配空间 strcpy(p->data,tmp);
if(tmp[strlen(tmp)-1]==5){ //除去最后一个控制符 ^E
free(p->data);
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hCon,color);
p->data[strlen(tmp)-1]='\0'; break; } }
p->next=NULL; //是最后的一个指针为空。 head=head->next; }
int Count_Space(LINE * &head){ //统计空格数 LINE *p=head;
int asc_space=32; //空格的ASCIC 码值 int count=0; do {
int Len=strlen(p->data); //计算当前 data 里的数据元素的个数
for(int i=0;i
if(p->data[i]==asc_space)count++; //计算空格数 }
while((p=p->next)!=NULL); //遍历链表 return count; }
int Count_Num(LINE * &head){ //统计数字数 LINE *p=head; int count=0; do {
int Len=strlen(p->data); //计算当前 data 里的数据元素的个数
for(int i=0;i
if(p->data[i]>=48 && p->data[i]
while((p=p->next)!=NULL); //遍历链表 return count; }
int Count_ZM(LINE * &head){ // 统计字母数
int count=Count_All_Word(head); //总的字符数,包含空格 int space_count=Count_Space(head); //空格数 int num_count=Count_Num(head);//数字数
return count-space_count-num_count; //返回文章的字母总数 }
int Count_All_Word(LINE * &head){ //统计文章的总字数 LINE *p=head; //保存链表的首地址 int count=0; //总字母数 do
{count+=strlen(p->data);} //计算当前行内的字符数 while((p=p->next)!=NULL); //遍历链表 return count; }
int Find_Word(LINE * &head,char *sch){ //统计 sch 在文章中出现的次数 LINE *p=head; int count=0; // int h=0;
int len1=0; //保存当前行的总字符数 int len2=strlen(sch); //待统计字符串的长度 int i,j,k; do {
len1=strlen(p->data);//当前行的字符数
for(i=0;i
if(p->data[i]==sch[0]) { k=0;
for(j=0;j
if(p->data[i+j]==sch[j])k=k+1; if(k==len2){count++;i=i+k-1;} } } }
while((p=p->next)!=NULL); //遍历链表 return count; }
void del_string_word(char *s,char *sch) {
// *s为输入的字符串 // *sch 为将要删除的字符
char *p=strstr(s,sch); //查询结果 char tmp[80]; int len=strlen(s); int i=len-strlen(p); int j=i+strlen(sch); int count=0;
for(int k=0;k
strcpy(s,tmp); //返回新的字符串
}
void Del_String(LINE * &head,char *sch){ //删除指定的字符串 LINE *p=head; do {
while(strstr(p->data,sch)!=NULL)del_string_word(p->data,sch); } while((p=p->next)!=NULL); //遍历链表 }
void OutPutTxt(LINE * &head){ //向屏幕输出文章 LINE *p=head; do
{ coutdata
} while((p=p->next)!=NULL); //遍历 链表 }
void Tj(LINE * &head){ //统计
cout
void main() {
setcolor(10); LINE *head; int opt;
cout
cout>opt; if(opt!=1)
{cout
// int n;int i;ElemType e; while(opt!=6){ //
switch (opt) { case 0:{
cout
cout
请选择操作
请选择操作
cin>>opt;
if (opt!=1&&opt!=2&&opt!=3&&opt!=4&&opt!=5&&opt!=6) {cout
case 1:{cout
cout
cout
case 2:{cout
setcolor(14);OutPutTxt(head);setcolor(10);cout
cout
case 3:{cout
cout
case 4:{cout
gets(sch);
}
cout
cout
setcolor(10);
cout
case 5:{cout
setcolor(14);
cout>tmp_sch;
gets(tmp_sch);
Del_String(head,tmp_sch); //删除指定字符
cout
OutPutTxt(head); //向屏幕输出 文章
setcolor(10);
cout
cout
cout
free_link(head);//释放链表空间 }//end of while }//end of else }
}
四、调试过程的系统测试情况及问题 4.1测试情况
程序运行,首先显示选择菜单,如图示:
选择1, 输入文章,界面运行结果如下:
按回车,调出开始菜单,输入2, 选择浏览,可以原样显示出刚才输入的文本:
回车后输入3,可以看到文章统计信息结果:
根据页面提示,回车
统计字符串模块,输入要统计的字符串,可以查找出该字符串在文章中出现过的次数。运行情况如下图示:
根据页面提示,回车
删除模块,输入要删除的字符串,执行删除后可以显示删除后的文本。界面如下:
根据页面提示,回车:
退出页面,执行后的结果如下:
4.2问题
①主流程进入死循环。.
②解决方案:每个循环都加break ,每跳出一个模块,opt 重新赋值为0。 输入多个变量,需要空格间隔时,程序只读空格前的变量
解决方案:输. 入函数用get( )函数,形式为:get(tmp),即可解决着个问题。 ③不识别自定义函数。
解决方案:函数定义前要函数声明,若不声明,则调用函数必须在函数定义之后,否则不识别。
④程序结束之后,链表仍占空间。
解决方案:在建立链表是所申请的内存空间在程序结束之前用free_link(LINE *&head)函数释放,即删除链表中的全部结点,且将链表头指针置为空。 4.3 注意事项:
① opt代表选项(共六个,多于六个显示“不可识别选项”)。
②建立文章,用链表存储,p=p->next=new LINE,即文章的每一行存储在一个结点中。 ③Ctrl+E为结束标志。 ④了解常用AS Ⅱ码。
课设总结
本实验采用链式顺序表结构实现了文章编辑的基本功能,实验过程中遇到了很多或大或小的问题,在这些问题的解决过程中,加深了对链表的理解,使我对链表操作的字符串的模
式匹配有了更深更全面的认识。
本实验提高了我对数据逻辑结构的特点和存储表示方式的认识,培养了我在具体应用中选择合适的数据结构和存储结构的能力。
通过该实验,使我熟悉了软件开发的基本过程,初步掌握了软件开发过程的问题分析、系统设计、程序编码测试等阶段的基本任务和技能方法。
使我的算法设计和算法分析能力以及运用所学理论知识和方法独立分析问题的能力得到全面的提高。
训练了我用系统的观点和软件开发的一般规范。使我认识到一个软件工作者所应该具备的科学的工作方法、作风和相互合作精神。
本实验的模块化比较强,各个模块之间用指针head 连接。认清模块化的概念给程序的顺利编制起到了很大的作用。分模块各个调试,可以减少很多不必要的麻烦。
参考文献
1] 耿国华等编著,数决结构—C 语言描述(第二版) ,西安电子科 技大学出版社,2008.7 [2] 赵文静, 祁飞等编著,数据结构与算法,科学出版社,2005.08
[3] 赵文静编著,数据结构-C++语言描述,西安交通大学出版社, 1999.01 [4] 孙鑫, 于安萍编著,VC++深入详解,电子工业出版社,2007.7
[5] COHOON & DAVIDSON 编著,C++程序设计,清华大学出版社, 2005.8