简单通讯录c++课程设计.docx
- 文档编号:24938163
- 上传时间:2023-06-03
- 格式:DOCX
- 页数:34
- 大小:243.13KB
简单通讯录c++课程设计.docx
《简单通讯录c++课程设计.docx》由会员分享,可在线阅读,更多相关《简单通讯录c++课程设计.docx(34页珍藏版)》请在冰豆网上搜索。
简单通讯录c++课程设计
C++课程设计
——简单通讯录管理
1.程序菜单功能
通讯录是一个简单的数据库库表,每一个记录(结点)包含个人所有通讯信息。
程序执行过程为:
显示主菜单,用户在choice:
处输入选项(按照功能列表输入1~9中的一个数字),按回车后执行相应的功能。
具体函数的功能请见下面4.提供典型测试数据组
2.分析,感想。
(1)、数据结构
程序采用一个单向链表类结构实现,每个结点代表一个通讯记录,链表类实现通讯录多个记录的管理工作。
(2)、新增功能
可批量输入,一次输入多个人的信息。
(3)、遇到的问题
这次课设遇到的问题较多,首先就是学过的知识无法融会贯通。
在完成课设时,许多知识点需要翻书查找(比如在输入输出流的部分),有时需要请教他人。
其次,是程序十分长,而且自己小错误不断,这样检查起来非常麻烦。
所以当运行程序时,出现了102个错误,其中大部分不是算法的问题,而是像少了“;”或是if中判断是否相等时用“=”而不是“==”。
最后,程序较长,编辑起来费力,有时一个算法出问题,其后的几个函数连带都会出问题,而且编译时没有显示有错误,这让检查起来非常麻烦,需要一遍又一遍阅读,有时还要请教别人一起阅读,耗时很长。
(4)、感想
这次课设成功完成,让我非常惊讶。
平时作业的一个程序,有时需要一个下午来完成。
现在,我发现原来我也可以完成如此复杂的程序。
更重要的是,这次课设让我的一些知识能记得更加深刻,对于编程也更加熟练。
而且,我知道请教他人的重要性,有时自己一个人想不出来的问题,问问同学,可以更好更快的解决。
最后,我知道了光把理论知识还不够,还要不断实践,这样才能将知识掌握得更加牢固,更加灵活。
3.提供有注释的源程序
#include
#include
#include
#include
#include
#include
classNode
{
charName[10];//姓名
intOfficePhone;//办公室电话
intHomePhone;//家庭电话
charMobilePhone[15];//手机号码
charE_Mail[20];//电子邮箱地址
Node*Next;//下一个结点指针
public:
Node(charna[]="sb",intop=0,inthp=0,charmp[]="0",charem[]="0")//构造函数,有缺省值
{
strcpy(Name,na);//将na中的姓名拷贝到Name中
OfficePhone=op;//将op中的数值赋给OfficePhone
HomePhone=hp;//将hp中的数值赋给HomePhone
strcpy(MobilePhone,mp);//将mp中的字符串拷贝到MobilePhone中
strcpy(E_Mail,em);//将em中的字符串拷贝到E_Mail中
}
voidShow()//显示结点数据
{
cout<<'\t'< } voidprint(ofstream&out)//将结点数据写入文件 { out.open("addresslist.text");//打开名为"addresslist.text"的文档 out<<'\t'< out.close();//关闭文档 } voidSetName(charna[])//修改姓名 { strcpy(Name,na); } voidSetOfficePhone(intop)//修改办公室电话 { OfficePhone=op; } voidSetHomePhone(inthp)//修改住宅电话 { HomePhone=hp; } voidSetMobilePhone(charmp[])//修改手机号码 { strcpy(MobilePhone,mp); } voidSetE_Mail(charem[])//修改电子邮箱地址 { strcpy(E_Mail,em); } friendclassAddressList;//将AddressList类说明为友元类 }; classAddressList { Node*HeadPtr;//链表首指针 Node*TailPtr;//链表尾指针 intTag;//排序状态标志 public: AddressList()//构造函数,创建空链表,将Tag的值置为1 { HeadPtr=NULL;//设置首指针的初始值为空 TailPtr=NULL;//设置尾指针的初始值为空 Tag=1;//Tag的初始值为1 } voidAddTail(Node*p)//将p指向的结点加入到链表的尾部 { if(HeadPtr==NULL)//如果链表为空,将数据添加在第一条 { HeadPtr=TailPtr=p;//链表为空,首尾指针均指向p } else { TailPtr->Next=p;//如果不为空,则尾指针的Next指向p TailPtr=p;//将p的值赋给TailPtr TailPtr->Next=NULL;//使TailPtr的成员Next为空 } } voidAddSort(Node*p)//将p指向的结点按Tag指定的顺序插入到链表中 { if(HeadPtr==NULL)//当链表为空时 { HeadPtr=TailPtr=p;//直接将数据记录在第一条 p->Next=NULL; } else//如果链表不为空 { Node*p1=HeadPtr,*p2=HeadPtr;//定义两个Node型指针变量 if(Tag==1)//按姓名排列 { p1=HeadPtr;//将首指针赋给p1 while(strcmp(p->Name,p1->Name)>0&&p1->Next! =NULL)//比较p中Name和p1中的大小 { p2=p1;p1=p1->Next; }//如果p大,就将下一个数据赋给p1,否则跳出循环 if(strcmp(p->Name,p1->Name)<=0)//如果p的成员Name比较小 { p->Next=p1;//将p的下一个指向p1 if(HeadPtr==p1)HeadPtr=p;//如果首指针等于p1,则将p的值赋给首指针 elsep2->Next=p; }//如果p1是第一个将p赋给HeadPtr,否则p2下一个指向p else//如果找不到比p的Name小的数据,就将p插在链表末尾 { p1->Next=p;//将p赋给p的下一条记录 p->Next=NULL;//而p的下一条为空 } } if(Tag==2)//按办公室电话排列,同按姓名排列的方法 { p1=HeadPtr; while((p->OfficePhone)>(p1->OfficePhone)&&p1->Next! =NULL) { p2=p1;p1=p1->Next; } if((p->OfficePhone)<=(p1->OfficePhone)) { p->Next=p1; if(HeadPtr==p1)HeadPtr=p; elsep2->Next=p; } else { p1->Next=p; p->Next=NULL; } } if(Tag==3)//按家庭电话排列,同按姓名排列的方法 { p1=HeadPtr; while((p->HomePhone)>(p1->HomePhone)&&p1->Next! =NULL) { p2=p1;p1=p1->Next; } if((p->HomePhone)<=(p1->HomePhone)) { p->Next=p1; if(HeadPtr==p1)HeadPtr=p; elsep2->Next=p; } else { p1->Next=p; p->Next=NULL; } } if(Tag==4)//按手机号码排列,同按姓名排列的方法 { p1=HeadPtr; while(strcmp(p->MobilePhone,p1->MobilePhone)>0&&p1->Next! =NULL) { p2=p1;p1=p1->Next; } if(strcmp(p->MobilePhone,p1->MobilePhone)<=0) { p->Next=p1; if(HeadPtr==p1)HeadPtr=p; elsep2->Next=p; } else { p1->Next=p; p->Next=NULL; } } if(Tag==5)//按电子邮箱地址排列,同按姓名排列的方法 { p1=HeadPtr; while(strcmp(p->E_Mail,p1->E_Mail)>0&&p1->Next! =NULL) { p2=p1;p1=p1->Next; } if(strcmp(p->E_Mail,p1->E_Mail)<=0) { p->Next=p1; if(HeadPtr==p1)HeadPtr=p; elsep2->Next=p; } else { p1->Next=p; p->Next=NULL; } } } } Node*LookUp(char*name)//按姓名查找结点,返回该结点指针 { Node*p=HeadPtr;//定义一个Node型指针,初始值为HeadPtr while(p! =NULL)//当链表不为空时 { if(strcmp(p->Name,name)==0)//循环比较数据中的Name成员 returnp;//如果存在,返回结点 p=p->Next;//将p的下一组数据赋给p } returnNULL;//如果不存在,返回值为空 } voidDelete(char*name)//删除指定姓名的结点 { Node*p1,*p2; if(HeadPtr==NULL)//当链表为空时 { cout<<"通讯录为空,无结点可删! \n"; } p1=HeadPtr; while(strcmp(p1->Name,name)! =0&&p1->Next! =NULL)//查找所在位置 { p2=p1;//将p1的值赋给p2 p1=p1->Next;//p1指向下一条记录 } if(strcmp(p1->Name,name)==0)//若找到该姓名对应的数据,删除该数据 { if(p1==HeadPtr)//如果p1在第一条,则将首指针指向下一条记录,将p1空出 HeadPtr=p1->Next; else//否则将p1的上一个记录的成员Next直接指向p1的下一条记录 p2->Next=p1->Next; deletep1;//释放p1的空间 cout<<"删除了一个数据! \n"; } else//若找不到,则输出"通讯录上没找到该条记录! " cout< \n"; } voidDeleteAll()//删除链表中全部结点 { Node*p;//定义一个Node型指针变量p while(HeadPtr)//当首指针不为0时,进行循环 { p=HeadPtr;//将head赋给p HeadPtr=HeadPtr->Next;//将head的下一条数据赋给head deletep;//释放p的空间 } } voidSort(inttag)//按Tag指定的关键字重新排序 {Tag=tag;//将tag的值赋给Tag Node*p1,*p;//定义两个Node型指针变量p1,p p=HeadPtr;//将首指针的值赋给p HeadPtr=NULL;//将首指针置为空 while(p)//当首指针不为空时,进行循环 {p1=p;//将p的值赋给p1 p=p->Next;//p指向下一条记录 p1->Next=NULL;//p1的成员Next指向空 AddSort(p1);//调用公有成员函数,将p1重新按关键字排序 } } voidShowAll()//显示全部结点,每10个显示一屏 { Node*p=HeadPtr;//定义一个Node型指针p,初始化为首指针的值 inti=1;//定义一个整型变量,计算现实的数据个数 system("cls");//清屏 while(p)//当p不为空时,进行循环 {cout< p->Show();//循环输出数据p p=p->Next;//将下一条记录的值赋给p if(! (i++%10))//当i是10的倍数时,暂停程序并清屏 {system("pause"); system("cls"); } } } voidSetTag(intt)//重置Tag的值 { Tag=t; } intGetTag()//获取Tag的值 { return(Tag);//返回Tag的值 } intCount()//计算链表中有多少个结点 { Node*p;//定义一个Node型指针p intt=0;//定义一个整型变量t,用来计算链表中结点的个数 p=HeadPtr;//将首指针的值赋给p while(p->Next! =NULL)//当链表不为空时 { t=t+1;//每当数据不为空时,t就加1 p=p->Next;//p指向下一条记录 }t=t+1;//因为当p->Next=NULL是就退出程序,所以末尾t要加1 returnt;//返回t } Node*GetHeadPtr()//获取链表首指针 { returnHeadPtr;//返回首指针 } ~AddressList()//析构函数,释放链表空间 {Node*p;//定义一个Node型的指针变量 while(HeadPtr! =NULL)//链表不为空,进行循环 { p=HeadPtr;//将第一条数据赋给p HeadPtr=HeadPtr->Next;//将下一条数据赋给首指针 deletep;//释放p的空间 } } #defineLensizeof(classNode)//定义常量Len为Node类数据的长度 voidCreateList(char*filename)//从二进制文件中读入数据,构造链表 { Node*p[100];//定义一个有100个数据空间的指针数组 inti=0,j=0;//定义两个整型变量,来记录第几条数据和读取数据的个数 fstreamfile(filename,ios: : in|ios: : binary);//定义一个文件流对象 if(! filename)//当文件为空时,无法打开 { cout<<"不能打开文件: "< exit (1); } file.read((char*)&Tag,sizeof(int));//从文件中读取Tag file.read((char*)&j,sizeof(int));//从文件中读取数据的个数 p[0]=newNode;//申请一个p的动态存储空间 while(file.read((char*)p[i],Len)! =0)//从文件中读取Len长度的数据不为0 { p[i+1]=newNode; AddSort(p[i+1]);//调用公有成员函数AddSort(),将文件中数据读取后,重新排序 } file.close;//关闭文件 } voidWriteToFile(char*filename)//将链表中的数据写入指定的二进制文件 { Node*p;//定义一个Node型的指针变量 p=HeadPtr;//将首指针的值赋给p fstreamfile(filename,ios: : in|ios: : binary);//定义一个文件流对象 if(! filename)//当文件为空时,无法打开文件 { cout<<"不能打开文件: "< exit (1); } while(p! =0)//当数据不为0时,将数据写入文件中 { file.write((char*)p,Len);//将p写入文件中 p=p->Next; } file.close;//关闭文件 } voidouttxt(char*file)//将数据从文件file导出 {Node*p=HeadPtr;//定义一个Node型指针变量,初始值为HeadPtr intn=1;//定义一个整型变量,作为数据的序号 fstreamout(file,ios: : out);//以写入的方式打开正文文件 if(! out)//定义一个输出文件流对象 {cout<<"不能打开该文件: "< exit (1); } while(p) {out< p=p->Next; } out.close(); } }; intmenu_select()//菜单实现 { char*a[]={"1.AddRecord","2.DeleteRecord","3.DisplayAllRecord","4.Query", "5.ModifyRecord","6.AddfromaTextFile","7.WritetoaTextFile", "8.Sort","9.DeletAll","0.Quit",NULL};//将菜单的选项赋给数组 inti,choice;//定义两个整型变量,一个用于输出选项,一个用于选择,并调用相关函数 do{ system("cls"); cout<<"\n\n========AddressBookManagingSyetem========\n\n"; for(i=0;a[i];i++)//循环输出选项
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 简单 通讯录 c+ 课程设计