C++课程设计报告案例.doc_第1页
C++课程设计报告案例.doc_第2页
C++课程设计报告案例.doc_第3页
C++课程设计报告案例.doc_第4页
C++课程设计报告案例.doc_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

东莞理工学院城市学院面向对象课程设计课程设计题目: 姓 名: 学 号: 专 业: 指导老师: 完成时间: 计 算 机 与 信 息 科 学 系题目:小型通信录管理系统姓名: 王晓明 专业:07计科1班 评分: 本章课程设计是设计一个实用的小型通信录程序,具有查询和删除功能,并且能够打开或修改指定文件及将多个文件组成一个文件。它完全使用类来实现,充分体现了面向对象的程序设计特点。本章的参考程序使用双向链表保存数据的底层数据结构,并使用C+标准库提供的list来实现这个链表的结构。由于利用list类,所以实现起来很简单。虽然这种方法超出一般的教材,但只要学习一下标准库,还是容易理解的。C+推荐使用标准库,这也是目前编程的方向,所以设计了本章作为选做内容,以便学生熟悉和了解C+的标准库。1、功能设计要求设计要求实现的功能较多,所以将它们分为几个部分叙述。1建立文件(1)存储文件可以使用默认文件名或指定文件名。(2)可以不保存输入记录,但需要确认是否保存输入记录。(3)如果已经有文件,只能在其后追加。(4)新增的记录可以不存人原文件中,也可以用原来的文件覆盖内存的内容(5)可以将指定文件的内容追加到目前内存中的链表后面。2文件的存取和显示(1)可以单独存取文件。(2)可以随时显示内存中记录的全部内容。(3)可以直接存取默认文件或指定文件。3删除记录(1)可以按”姓名”或”电话”方式删除记录并更新内存链表内容。(2)能给出被删除记录的信息。(3)如果已经是空表,删除时应给出提示信息并返回主菜单。(4)如果没有要删除的信息,输出没有找到的信息。(5)删除操作仅限于内存,只有执行存记录时,才能覆盖原记录。4查询记录(1)可以按”姓名”或”电话”方式查询记录。(2)能给出查询记录的信息。(3)如果查询的信息不存在,输出”没有找到”的信息。5整体性能(1)应可以随时检索、删除或增加新记录,也可以保存或取消新的记录(2)姓名可由字符和数字混合编码。(3)电话号码可由字符和数字组成。(4)将输出信息加上栏头,例如: 姓名 电话 李玉梅 (86)10-62543321 张三 86 551 9823555 LesHancockZhang San 055136994698(5)使用菜单实现功能的正确选择。6测试程序(1)应列出测试大纲对程序进行测试。(2)应保证测试用例能测试到程序的各种边缘情况。2、使用list类的成员函数 list的对象的定义方式是: list obj 其中T是链表所存储的数据类型,也就是链表的每一个结点的数据类型。 list类中使用typedef定义的常用的数据类型是iterator和const_iterator,可将它们看成是指向每条记录的指针和指向记录的const指针。 在通信录程序中使用到的list类的成员函数如下: 1boollist:empty()const 当且仅当list为空时,就返回true。 2size_tlist:size()const 返回链表中记录的元素个数。该函数的运行复杂度是线性的,即O(N)。 3iteratorlist:begin()返回一个iterator,指向此链表的开头。4iteratorlist:end()返回一个iterator,指向此链表的尾端,这里的尾端指的是链表的最后一个元素之后,即链表中实际存有元素的范围是(begin(),end()。5const_iteratorlist:begin()const返回一个const iterator,指向此链表的开头。6const_iteratorlist:end()const返回一个const_iterator,指向此链表的尾端,这里的尾端指的是链表的最后一个元素之后,即链表中实际存有元素的范围是lbegin(),end()。7voidlist:push_back(constTt)将元素t安插于链表尾。8iteratorlist:erase(Ueratorpos)删除pos所指向的元素,返回指向被删除元素后面一个元素的iterator。9voidlist:clear()删除链表中的所有元素。3、结构和类在通信录中共定义了1个结构和3个类,下面对它们加以说明。(1)结构Recordstruct Record string name; /姓名 string tel; /电话号码; 如果使用字符串,其长度必须事先定义。使用string类,存储对象需要的长度则随具体对象的实际长度而定。在使用VS7(Microsoft Visual Studio.NET 2003)和C7(MicrosoftVisualC+.NET 2003)软件时,不会有任何问题。但在使用VisualC+60时,由于VC6本身存在一些问题,所以也给本设计带来一个问题:使用getline()函数需要再按一次”回车”键,从而产生交互错误。本程序将在实际设计中做进一步说明,此处不再赘述。(2)类RecordList类RecordList是一个针对通信录做了特殊处理的链表,它继承于list,即以指向结构Record的指针为元素的链表。class Recordset:public list friend ostream& operator (istream& iS,RecordList& r1);public: void clear( ): iterator erase(iterator where); RecordList();类RecordList可以直接使用类list中定义的所有函数,但重写了clear()函数、erase()函数和增加了析构函数,并重载了输入、输出操作符。这是因为类list的删除元素的操作只会释放存储元素的空间;对于本程序来说,就是只释放Record指针,却并不会释放该指针所指向的对象。因此,类RecordList覆盖了基类中的clear()函数、erase()函数,使得其在删除元素时,首先释放该元素(即Record指针所指向的Record对象),然后再调用基类中被覆盖的同名函数以实现删除元素的功能。增加了析构函数是为了链表被销毁的同时,也销毁其所记录的所有对象。重载了输入、输出操作符是便于从输入、输出流中还原或保存链表。(3)类AddressListAddressList类是处理通信录的底层类,针对增加纪录、删除纪录、查询纪录以及保存和读取纪录等操作进行与底层数据结构相关的处理,该类不涉及任何与用户界面或与用户交互相关的操作。该类以”包含”关系(has-a)持有一个RecordList类的对象recList,作为保护型数据成员,这是存取纪录的底层数据结构。Class AddressListprotected: RecordList recList; /RecordList的对象作为数据成员public:typedef RecordList:iterator lterator;/从通信录中寻找一个记录virtual lterator findRecord(string pattern,int type,Iterator from):/其他成员函数virtual void addRecord(Record *rec);virtual lterator removeRecord(1terator it);virtual void saveRecords(ostream& OS);virtual int loadRecords(istream& is);virtual AddressList(),const int size() const return (int)recListsize();const bool empty() const return recListempty();virtual void clear() recListclear():Iterator first() return recListbegin();Iterator pastEnd() return recListend();在类AddressList中定义的一些函数直接使用了类RecordList的函数,没有增加太多的功能,如addRecord()只是调用了类RecordList继承自基类的push_back(),removeRecord()只是调用了类RecordList重写了的erase()。需要特别解释的是findRecord()函数,它用于从通信录中寻找一个符合条件的记录,并返回指向该记录的iterator。该函数将从给定的iterator开始,按递增的顺序依次考查每一记录,直到找到符合条件的记录或者到达通信录的末尾。在iterator迭代遍历记录时,采用如下的代码:Iterator it;Iterator it_end=recListend(),for (it=from;it!=it_end;it+) .这里from是迭代开始的位置,it_end是通信录的末尾。若想遍历整个通信录找出所有符合条件的记录,from可以第一次取值recListbegin(),之后每次取前一次运行findRecord()所得返回值增1,直到findRecord()返回it_end为止。(4)类AddressBook类AddressBook是处理通信录操作的面向用户使用的类,包含所有功能的用界面及用户交互的实现。class AddressBook:public AddressListprotected: bool isModified; /通信录是否已被修改还未保存public: AddressBook():virtual AddressBook():/开始通信录的用户界面操作virtual void start();/菜单处理函数virtual void handleMenu():/显示记录virtual void displayRecords()/查询记录virtual void queryRecord(),/增加记录virtual void addRecord();/删除记录virtual void removeRecord():/保存记录virtual void saveRecords();/读取记录virtual void loadRecords();/结束程序virtual void quit();/清空当前通信录virtual void clear():protected:/菜单选择函数char menuSelect();/显示表头void dispTable();该类继承了类AddressList,可以直接使用它的直接基类AddressList中的函数。在运行通信录时只要新建一个AddressBook类的对象,就可以通过这个对象自动执行与用户交互的操作。类AddressBook的构造函数将调用欢迎界面成员函数start(,函数start()将调用菜单处理函数handleMenu(),在成员函数handleMenu()中,将反复调用菜单选择函数menuSelect(),然后依据用户的选择调用相应的处理函数displayRecords()、queryRecord()、addRecord0、removeRecord()、 saveRecords()、 loadRecords0、clear()、quit()等。成员函数displayRecords()会通过iterator迭代遍历整个通信录,显示所有的记录。成员函数queryRecord()会首先获得用户要求的查询条件,然后通过前面介绍的方法反复调用类AddressList的findRecord()函数,找出所有匹配条件的记录并显示出来。成员函数addRecord()将要求用户输入必要的信息以构建新的Record对象,然后将指向该对象的指针作为链表的元素,通过调用类AddressList的addRecord()函数添加到通信录的末尾。成员函数removeRecord()会首先获得用户要求的查询条件,使用该查询条件来找到用户,想要删除的确切记录,将每一个符合条件的记录显示给用户看,询问用户是否确定删除该记录;若确定删除,则调用类AddressList的removeRecord()函数完成记录删除。成员函数saveRecords()让用户输入文件名,然后建立文件输出流,再调用类AddressList的saveRecords()函数完成。成员函数loadRecords()会将从文件读入的记录追加到当前通信录的末尾,所以如果希望当前通信录与文件中记录的通信录完全一致,就应该先调用成员函数clear(),再调用成员函数loadRecords()。loadRecords()会首先让用户输入文件名,然后建立文件输入流,最后调用直接基类AddressList的loadRecords()函数完成读取操作。成员函数clear()会首先检查当前通信录是否已被改动并提示用户进行保存,然后调用直接基类AddressList的clear()函数完成清空操作。成员函数quit()会首先检查当前通信录是否已被改动并提示用户进行保存,然后运行语句delete this;来销毁自己(AddressBook)的对象,最后运行exit()函数结束程序。(5)类的UML图图10-1是使用类的短式形式表示的UML结构图。4、参考程序本设计由3个cpp文件及其相应的3个头文件组成。(1) address文件1 addressh文件#ifndef H_ADDRESS H ABCDE#define H ADDRESS HABCDE using namespace std;/每一条记录的结构struct Record string name; /姓名 string tel: /电话号码);/用于存储通信录的链表/使用的底层数据结构是双向链表class RecordList:public list friend ostream& operator (istream& is, RecordList& r1);public:/销毁链表中记录的所有Record所占用的内存空间/该函数覆盖了基类中的同名函数void clear()/遍历整个链表,提取并销毁所有Recorditerator iter;iterator it_end=end();for (iter=begin(),iter!=it_end;iter+)delete *iter;/调用超类的函数来清空链表list:clear();/销毁指定的记录,然后从链表中将其删除/该函数覆盖了基类中的同名函数iterator erase(iterator where)delete *where;return list:erase(where);RecordList() this-clear();;#endif /H_ADDRESS_H_ABCDE2addresscpp文件#include #include include “addressH”include “AddressListH”include “AddressBookH”int main()new AddressBook; /开启通信录return 0;ostream& operator (ostream& os,cohst RecordList& c_r1)RecordList:const_iterator it;RecordList:const iterator it_end=c_r1end();for (it=c_r1begin(),it!=it_end;it+)osname ntel (istream& is,RecordList& r1)Record* rec;string name;while (true)/注意这里使用的是全局的getline()函数,而不是istream的成员函/数。全局的getline()函数将从istream中取出最后个分隔符,/而istream的成员函数getline则不会getline(is,nanle);if ( name = = “ “) break;rec=new Record;rec-name=name;getline(is,rec-tel);r1Push_back(rec);return is;(2) AddressLiSt文件1AddressList.h文件#ifndef H_ADDRESSLISr H AAA#define H_ADDRESSLIST H AAA#include #include #include “addressH”using namespace std;/处理通信录操作的底层类,包括增加记录、删/除记录、查询记录以及保存和读取记录的函数/该类不涉及任何关于用户界面的操作class AddressListprotected:RecordList recList; /使用对象成员作为数据成员public:typedef RecordList:iterator lterator;/向通信录中添加新的记录virtual void addRecord(Record* rec);/从通信录中删除一个记录virtual lterator removeRecord(1terator it);/从通信录中寻找一个记录virtual lterator findRecord(string pattern,int type,Iterator from);/将通信录保存到输出流中virtual void saveRecords(ostream& os);/从输入流中读入数据并追加到当前通信录的末尾virtual int loadRecords(istream& is);virtual AddressList():/获得通信录中存储的记录数const int size() const return (int)recListsize();/通信录是否为空const bool empty() const return recListempty();/清空通信录virtual void clear() recListclear(),/获得通信录的第一条记录Iterator first() return recListbegin();/获得通信录超过最后一条记录之后的迭代器Iterator pastEnd() return recListend();#endif /H_ADDRESSLIST_H_AAA2AddtessListcpp文件#include “addresslisth”AddressList:AddressList()recListclear();*功能: 向通信录中添加新的记录*参数:rec,指向新记录的指针*void AddressList:addRecord(Record* rec)if (rec !=NULL)recListpush_back(rec); *功能:从通信录中删除一个记录*参数:it,指向欲删除记录的迭代器*注意:it应是可提领的迭代器,可以通过findRecord()获得*AddressList:Iterator AddressList:removeRecord(AddressList:Iterator it)return recListerase(it);*功能:从通信录中寻找一个记录*参数:pattern,欲寻找的记录的指定域与pattern相等* type, 为1表示欲寻找记录的名称(name) 与pattern相等;* 为2表示欲寻找记录的电话(tel)与pattern相等。* from,从from开始寻找匹郾的记录。*返回:若找到了则返回指向第一个匹配记录的迭代器,*若找不到则返回的迭代器等于pastEnd()的返回值。*注意:from应是可提领的迭代器。*第一次调用可以用first(),之后使用上一次findRecord()的返回值增1*直到返回pastEnd(),便可以获得所有匹配的记录。*AddressList:Iterator AddressList:findRecord(string pattern,iht type,AddressList:Iterator from)Iterator it;Iterator it_end = recListend();for (it=from;it!=it_end;it+)if (type= =l & (*it)-name= =pattern)| (type= =2 & (*it)-tel = = pattern) break;return it;*功能:将通信录保存到输出流中*参数:OS,指定的输出流*void AddressList:saveRecords(ostream &os) os recList;return size()-ori;(3)AddressBook文件1AddtessBookh文件#ifndef H_ADDRESSBOOK_H_NNN#define H_ADDRESSB00K_H_NNN#include “addresslistH”/处理通信录操作的面向用户使用的类,包含所有功能的用户界面及用户交互的实现class AddressBook:public AddressListprotected: bool isModified; /通信录是否已被修改还未保存public: AddressBook(); virtual AddressBook();/开始通信录的用户界面操作virtual void start(),/菜单处理函数virtual void handleMenu();/显示记录virtual void displayRecords()/查询记录virtual void queryRecord();/增加记录virtual void addRecord();/删除记录virtual void removeRecord();/保存记录virtual void saveRecords();/读取记录virtual void loadRecords();/结束程序virtual void quit();/清空当前通信录virtual void clear():protected: /菜单选择函数 char menuSelect(), /显示表头 void dispTable(),;#endif /H_ADDRESSBOOK_H_NNN2AddtessBookcpp文件 本来一些成员函数使用string类来设计,既简洁又可提高程序的性能;但考虑到使用VC的用户较多,所以改写了部分成员函数的实现方式。为此,在下面程序的实现中,将给出典型的对比设计方法。#include #include #include “addressbookH”using namespace std;AddressBook:AddressBook() isModified=false;start();AddressBook:AddressBook()*功能:显示欢迎画面,并开始进行用户交互处理*void AddressBook:start()cout “n” “t*n” “t* 这是一个 *n” “t* 简单的通信录程序 *n” “t*可以对通信录进行简单管理 *n” “t* 欢迎使用通信录 *n” “t*n” “n”;handleMenu();*功能:显示通信录菜单,返回用户选择的选项*返回:用户选择的选项,是19之间的一个字符*char AddressBook:menuSelect() cout “n” “1显示记录n” “2查询记录n” “3增加记录n” “4删除记录n” “5保存记录n” “6读取记录n” “7新建通信录n” “8结束运行n”“n左边数字对应功能选择,请选18:”;char choice2;while (true)cingetline(choice,2);if (choice08)cout “n输入错误, 重选1-8:”;else break;return choice0;*功能;根据用户选择的项目调用相应的处理函数*void AddressBook:handleMenu()while(true)switch(menuSelect() case 1 :displayRecords() break;case 2 :queryRecord(); break;case 3 : addRecord(), break;case 4 : removeRecord();break;case 5 : saveRecords(): break;case 6 : loadRecords(): break:case 7 : clear(); addRecord(): break:case 8 :quit(); *功能:打印用于显示记录信息时的表头*void AddressBook:dispTable()cout “姓名tt电话” endl;*功能:显示通信录中的所有记录*void AddressBook:displayRecords()if(recListsize()= =0)cout“没有记录return; dispTable():Iterator it,Iterator it_end=recListend();for (it=recListbegin(); it!=t_end;it+) cout name “tt” tel “n”;cout “一共有 size() “条记录n” endl;/*功能:首先检查通信录是否已保存,然后清空当前通信录中的所有记录*注意:该函数覆盖了基类中的函数*/void AddressBook:clear()if (isModified) /已改动, 未保存cout “通信录已改动, 是否保存?(Yn)n”;char choice2:cingetline(choice,2);if (choice0!=n & choice0!=N) saveRecords(); AddressList:clear();IsModified=false;/*功能:查询指定记录*/void AddressBook:queryRecord()if (empty()cout “记录是空表,退出查询操作! “ endl;return; /选择获取需要查询的记录的方式cout “可以通过姓名或电话删除记录n” “1通过姓名n” “2通过电话n”,char choice2:cingetline(choice,2):while (true)if (choice0 !=1 6& choice0!=2)cout“输入错误,重选1-2: “;cingetline(choice,2);elsebreak; int type=static_cast(choice0)-48;/输入需要匹配的字符串if (type= =1) cout “请输入姓名: “;elsecout “请输入电话: “;char pattern201; cingetline(pattern,20);*这里限制字符串的长度,注意不要越界*应该使用 “string pattern; “, 但VC 60*不能接受空格,所以采用字符数组形式* int findCount 尝 0: /找到匹配的记录Iterator it=findRecord(pattern,type,first();Iterator it_end=pastEnd();disprable(),while (it!=it_end)findCount+;cout name “tt” tel “n”;/取下一条匹配的记录it=findRecord ( pattern,type,+it ); cout “一共找到了” findCount “条记录n” endl;*功能:向当前通信录追加新的记录*注意:该函数重载了基类中的函数*void AddressBook:addRecord()cout“输入数据,输入姓名为0时结束。n”;while(true)/输入新记录char temp20,coutname=temp;cout rec=temp;/将新记录加入链表AddressList:addnecord(rec);isModified =true; /记录已改动,未保存说明:如果使用string类,效果更好。下面是实现本功能的程序代码while(true)/输入新记录string name;cout name=name;coutrel);/将新记录加入链表AddressLiSt:addRecord(rec);同理,下面的成员函数removeRecord()中的判断,可以使用如下替代方法string str;getline(cin,str);while(true) if (str0!= 1 & str0!=2)cout“输入错误,重选1-2:”;getline(cin,str);else break;*功能:从当前通信录移除指定的记录*注意:该函数重载了基类中的函数*void AddressBook:removeRecord()if(empty()cout “通信录已空,退出删除操作!”endl;return; /选择获取需要删除的记录的方式cout “可以通过姓名或电话删除记录n”; “1通过姓名n” “2通过电话n”;char choice2;cingetline(choice,2);while(true)if (choice0 !=1 & choice0 !=2)cout“输入错误,重选1-2:”;cingetline(choice,2); int type = static_cast(choice0) -48;/输入需要匹配的字符串if (type= =1) cout “请输入姓名:”flush;else cout“请输入电话:”flush;char pattern20;cingetline(pattern,20):int

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论