华南理工大学《C++程序设计》大作
业报告
作业名称: 《高级程序语言设计C++》大作业
学院:计算机科学与技术
专业:计算机科学与技术(全英创新班)
学生姓名:黄炜杰
任课教师:徐雪妙
提交日期: 2013年6月x日
一、问题描述
【设计个人通信录管理系统】
功能包括编辑好友资料、查看好友资料、搜索好友资料、发送信息/email等。
二、系统设计
1、类体系设计
对话框类:
通讯录Dlg .h 主界面的类
ViewMenu .h “查看”界面Conglation .h 查看最近生日的人时,
发送邮件的类Editmenu .h “编辑”界面InputDlg .h 新建联系人时,输入信息
的类
ModifyDlg.h 修改联系人信息的类
Contact .h “联系”界面Send.h 发送email/信息的类
SearchMenu .h “查看”界面
非对话框类:
WhoHasBirthday.h 查看最近谁生日的类
AdressBookBase.h 基类,用于保存记录.搜索.创建合并文件.获取时间.排序ABFschoolMate.h AdressBookBase.h的public派生类
ABFworkMate.h AdressBookBase.h的public派生类
ABFfriend.h AdressBookBase.h的public派生类
ABFrelative.h AdressBookBase.h的public派生类
2、类的说明,包含数据成员和成员函数的功能描述。
通讯录Dlg类
此为主界面的类,主要功能为弹出主窗口,链接Edit、View、Search、Contact菜单
通讯录Dlg::OnBnClickedCancel():按下Exit键时,将会弹出message询问用
户是否确定退出通讯录Dlg::OnBnClickedEdit():按下Edit键时,将会弹出编
辑的窗口
通讯录Dlg::OnBnClickedSearch():按下Search键时,将会弹出搜索窗口
通讯录Dlg::OnBnClickedView():按下View键时,将会弹出查看窗口
通讯录Dlg::OnBnClickedButton1():按下contact键时,将会弹出联系窗口
EditMenu 类
此为编辑界面的类,主要功能有显示所有客户,并提供新建、修改、删除联系人的链接
CEditmenu::OnInitDialog()次函数作用是初始化列表,其中先对列表风格进行了初始化,设为可以全行选中和栅栏风格,接着分别插入了8列,以显示“name
“、”birthday”等,接着分别读取了Adressbook1~4,计算出4个文件的长度;接着分别逐个读取了adressbook里面的字符串,读一个就把一个插入到列表的
相应位置
CEditmenu::OnBnClickedNewaccount()显示弹出了一个新建联系人时填信息的
窗口,接着判断这个窗口的返回值是不是IDOK。如果OK的话,则确认新建用户,(填信息的窗口把数据保存在temp.txt里面了),打开temp.txt,用循环体读
取各条记录,每条记录依次读取6个字符,第一个为分组类型,后面5个按顺序
逐个读取字符串,一次把前四个字符摆到列表里,然后根据类型把第五个摆到
相应的位置
CEditmenu::OnBnClickedCancel()按下back键时,退出编辑界面,同时,保存
列表里面的数据到adressbook1~4中。保存的具体步骤:先是获取列表一共有多少行,然后以ofstream打开4个adressbook,新建adressbook.h的4个派生对象,根据列表的行数进行循环,根据学校名、公司名、认识地点、称呼是否为空来
确定分组,然后根据分组来确定调用adressbook指针的哪个对象来保存数据。CEditmenu::OnBnClickedModify()按下修改键时,获取当前选择的位置,根据
学校名、公司名、认识地点、称呼是否为空来确定分组,然后把类型和其他5项信息保存到temp.txt里面像弹出修改界面,判断修改界面的返回值是否IDOK,
是的话确定修改,(修改界面把修改的数据保存在temp.txt里面)。接着打开temp.txt,分别读取类型,name.birthday.phone.emial,接着把他们放到列表的相应位置
CEditmenu::OnBnClickedDelete()按下delete键时,先获取选中的位置,然后
弹出messagebox询问用户是否确定删除,是的通过deleteitem()函数删除相
应的行
ViewMenu类
此类主要功能为查看联系人,提供了查看所有、按组查看等功能
ViewMenu::OnInitDialog()和CEditmenu::OnInitDialog()的一模一样,同时多了一项,调用adressbookbase的函数来获取当前的年份、月份、日期、星期,
然后把时间输出在窗口下方
ViewMenu::OnBnClickedViewall()按下此键时,先用DeleteAllItems();清空
所有内容,再把列全删除了,再调用OnInitDialog()来刷新列表
ViewMenu::OnBnClickedViewbygroups()按下viewBygroups键时,先用DeleteAllItems();清空所有内容,再把列全删除了,然后重新设置列为分组-名字-生日-电话-email和其他4项数据,然后调用基类的creatAllText()函数生成一个合并文件client.txt,读取client.txt,依次读取类型、名字等各项数据,然后根据类型放到不同的位置
ViewMenu::OnBnClickedWhobornonmonth()按下Whobornonmonth按钮时,先判
断输入的月份是否为空,空的话调用OnInitDialog()函数刷新列表,不是空的话,新建一个标记数组,初始化全部为1,调用creatAllText()函数生成一个合并文件client.txt,读取client.txt,读取生日的相应位置,判断与条件是否
符合,不符合的话标记数组相应位置变为0,最后循环一次标记数组,如果是1
的话,就把相应的数据保存到temp.txt里面,最后关闭temp.txt。接着打开
temp.txt,如果为空的话,提示搜索不到,否则,依次读取各条记录,把列表
清空,然后插入各项数据。
ViewMenu::OnBnClickedWhobirthrecently()先调用Adressbookbase的函数来
获取当前月日,然后调用creatalltext()函数生成一个合并文件,新建一个
标记数组,初始化为1,然后依次读取每个人的生日月日,然后把当前月日和联系人的月日传递到haveBirthdayRecent()函数,来计算2个日期的差距,如果差距不是小于等于5天,就把标记数组相应的位置变为0,最后循环一次,把标记
数组为1的联系人保存到temp.txt里面,接着打开temp.txt,如果为空的话,提示搜索不到,否则,依次读取各条记录,把列表清空,然后插入各项数据。ViewMenu::OnBnClickedSortbyname()
ViewMenu::OnBnClickedSortbyphone()
ViewMenu::OnBnClickedSortbybirthday()
ViewMenu::OnBnClickedButton1()这四个函数的原理是一样的,按下按键之后,调用adressbookbase的sort()函数进行排序,根据参数的不同,进行不
同的排序,排序之后生成了temp.txt。这时,依次读取各条记录,把列表清空,然后插入各项数据。
SearchMenu类
此函数为搜索界面的类
SearchMenu::OnInitDialog()初始化列表,和CEditmenu::OnInitDialog()一模一样,请参考
SearchMenu::OnBnClickedSearchbotton()当输入条件为空时,调用SearchMenu::OnInitDialog()来刷新界面,当学校名、公司名、称呼、认识地
点有2个或以上存在时,提示搜索不到,因为这样的联系人不存在。接着新建基类Adressbook对象和4个派生类对象,然后根据学校名、公司名、称呼、认识地点是否为空来确定用户类型,根据类型不同调用不同的函数来搜索,把搜索结
果保存到temp.txt里面,接着打开temp.txt,如果为空的话,提示搜索不到,
否则,依次读取各条记录,把列表清空,然后插入各项数据。
Contactmenu类
此类为联系的界面,主要提供打电话,发信息,发邮件功能的链接ContactMenu::OnInitDialog()和EditMenu::OnInitDialog()一模一样,请参考
ContactMenu::OnBnClickedcall()先判断否选中用户,没选中的话提示用户没
选中,否则通过getitemtext()函数读取选中的联系人的名字,然后新建一个Cstring,格式为Calling to 联系人。。。。弹出messagebox输出刚才的cstring,模拟打电话的窗口
ContactMenu::OnBnClickedsendmessage()
ContactMenu::OnBnClickedsendemail()这两个函数的原理是一样的,先判断
否选中用户,没选中的话提示用户没选中,否则通过getitemtext()函数读取
选中的联系人的名字,电话/email,然后保存到temp.txt里面,然后调用发信息/email的窗口
CongaltionEmail类
此类为搜索出最近5天生日的人之后,按了“send conglation email”按钮之后弹出的窗口,用于发送祝贺emai
ConglationEmail::OnInitDialog()读取保存在temp.txt的名字读取出来,然后把名字初始化到收件人的位置,并且初始化祝贺内容为"My dear , Happy Birthday To you !"。
ConglationEmail::OnBnClickedOk()按下send键时,弹出messagebox提示用户发送成功
Send类
此类为发送短信/emial的窗口,提供编写短信/emil并发送功能
Send::OnInitDialog()先把之前保存在temp.txt里面的联系人读取,然后把名字初始化到收件人的位置,并且初始化祝贺内容为"I haven’?¥t seen much of you lately . Would you like to go to the coffee shop with me ?" Send::OnBnClickedOk()按下send键时,弹出messagebox提示用户发送成功Send::OnBnClickedButton1()
Send::OnBnClickedButton6()
Send::OnBnClickedButton7()
Send::OnBnClickedButton8()
Send::OnBnClickedButton9()
Send::OnBnClickedButton10()这6个函数原理一样,为信息模板下的按钮,按下按钮之后,分别调用这6个函数,把短信内容改为模板提示的信息,如"I haven’t seen you in years . What have you been upheld to lately ?"
InputDlg类
这个类是editmenu下点击new adress弹出的窗口的类
InputDlg::OnInitDialog()初始化选择的分组是同学,动态内容是“学校名”InputDlg::OnBnClickedC1()
InputDlg::OnBnClickedC2()
InputDlg::OnBnClickedC3()
InputDlg::OnBnClickedC4()这四个函数的原理一样,点击之后,分别把分组选择变为同学、同事、朋友、亲戚,把动态内容也改变为相应内容。InputDlg::OnBnClickedOk()先通过几个if语句判断输入是否合法,不合法的话return,合法的话,把联系人信息保存到temp.txt里面
ModifyDlg类
这个类是editmenu下点击modify弹出的窗口的类,用于修改用户信息ModifyDlg::OnInitDialog()先把之前保存在temp.txt里面的联系人信息读出,然后把信息初始化到窗口中,
ModifyDlg::OnBnClickedOk()先通过几个if语句判断输入是否合法,不合法的
话return,合法的话,把联系人信息保存到temp.txt里面
WhoHasbitrhday类
这个类是按了view-谁最近生日时弹出的窗口
WhoHasBirthday::OnInitDialog()把刚才保存在temp.txt的搜索结果读进列表
里面
WhoHasBirthday::OnBnClickedButton1()先判断否选中用户,没选中的话提示
用户没选中,否则通过getitemtext()函数读取选中的联系人的名字,电话
/email,然后保存到temp.txt里面,然后调用发信息/email的窗口
AdressBookForBase类
这不是对话框的类,是用来处理数据的,是ABFschoolMate、ABFworkMate、ABFfriend、ABFrelative的基类,其他4个派生类功能与此相同,故不重复描述AdressBookForBase::newAccount()此函数为虚函数,但是空的,派生类的
才生效,故在此说派生类的相应函数的作用与原理。函数接收5个参数,然后把
5个参数相应的保存到adressbook1~4的相应位置,保存的是120个字符的定长记录。
AdressBookForBase::Search()这函数接收了5个参数,作为搜索条件,一开始
读取client.txt或者adressbook1~4来作为搜索对象,然后新建一个标记数组,初始化为1,然后逐个条件判断,如果条件为空,则不判断,否的进行判断,判断结果与条件不符的话,标记数组变为0。然后循环一次,标记数组为1的话,
把相应联系人保存到temp.txt里面
AdressBookForBase::creatAllText()此函数的作用是合并adressbook1~4,分
别读取这四个文件,然后分别把每个联系人的信息保存到client里面,定长记
录变为130,多处了10个字符来保存联系人分组。
AdressBookForBase::getMonth()
AdressBookForBase::getDay()
AdressBookForBase::getYear()
AdressBookForBase::getXingQi()这四个函数的原理是一样的,先用time(0)获取现在到1970年1月1日00:00的秒数,然后把秒数经过运算分别转化为年月日和星期
AdressBookForBase::haveBirthdayRecent()接受4个参数,转化为2个日期,
把这2个日期先转化为指定日期是当年的第几天,然后把这2个天数相减,求相
差的天数,并把天数返回AdressBookForBase::sort(int kind)先调用creatAllText()来合并所有联系人,然后打开此文件,根据参数不同,定位每
个联系人的不同位置进行排序,如,类型是1-名字,就读取行数*记录长度+
名字的位置,然后保存到一个string数组里面,对string数组进行排序,把排
序结果保存到int数组里面,然后根据int数组的排序,把client里面的信息重
新排序保存到tenmp.txt里面;
3、程序流程图
在Main目录下,按edit,可以进行新建、修改、删除操作。按修改和新建时,都会弹出窗口获取信息
在Main目录下,按View,可以查看所有人,按分组查看,按姓名、电话、生日、email排序查看,查看某月生日的人,和5天内生日的人,按“5天内生日的人”时,弹出对话框,可以发送邮件祝贺
在Main目录下,按search,输入信息,可以按信息查找用户
在Main目录下,按contatc,选中联系人,可以对其打电话,发送信息、邮件,发现信息邮件时,会弹出编辑框编辑信息/email;
三、程序测试
【测试edit - new adress功能】依次新建3个同学、3个同事、3
个朋友、3个亲戚
[测试结果]新建账户成功,新建途中,查错功能正常
(图解:输入少了一位数字的手机号,被检测出并提示)
【测试edit - modify功能】直接按modify,系统提示“No account
seleted”,选择“forest”联系人,弹出修改框,姓名和生日不能修改,把手机号139********改为139********
[测试结果] Forest的联系电话修改成功
【测试edit - delete功能】直接按delete,系统提示“No account
seleted”,选择用户“Jason”,按delete并确认
[测试结果]联系人 Jason被成功删除
【测试edit 的保存读取功能】在做完前述步骤之后,退出软件,重
新进入
[测试结果]成功保存读取,列表的内容和上一次操作后的内容一致
【测试View-View by groups功能】按下view by groups按钮
[测试结果] 列表显示内容成功按分组显示
【测试View-View all功能】按下view all 按钮
[测试结果]列表成功显示所有联系人
【测试View-Sort by name、Sort by phone、Sort by birthday、Sort by email功能】分别按下这四个按钮
[测试结果] 列表成功按这4项内容排序显示
【测试View-who bithday recently功能】点击按钮,弹出对话框
[测试结果]成功显示了最近5天生日的人,选择用户后点击send congalution email按钮,成功弹出email并成功发送
【测试search功能】依次查找姓名“Xizt”,出生月份“12”和双重条
件月份“12”公司名称“IBM”
[测试结果] 成功搜索出联系人
【测试contatc-call功能】选择联系人,按call
[测试结果]成功弹出窗口
【测试contatc-email.message功能】选择联系人,按send email [测试结果]成功弹出窗口并初始化收件人和短息内容,点击模板时,短信内容
改变
【测试结论】:程序运行正常,不存在明显错误
四、使用说明主界面如下
在界面下按” edit”按钮,会弹出如图所示的编辑按钮
在edit界面下按newAdress,弹出如图窗口
可以在左边选择联系人的类型,选了之后,最后一个编辑框提示的内容也会有所改变,依次输入联系人信息,信息不能为空。输入完之后按“OK”就能保存
在edit界面选中联系人,按modify按钮,弹出如图窗口
可以修改联系人除姓名、生日以外的信息
在edit界面选中联系人,按delete按钮,会提示是否确定删除联系人,确定的话联系人就被删除。
在主菜单下按view按钮,弹出如下窗口
下方能显示今天的日期
按View all,能看到所有人的信息
按View by groups,能按分组看到所有人信息
按Sort by name,能按姓名排序看到所有人信息
按Sort by phone,能按电话排序看到所有人信息
按Sort by birthday,能按姓名排序看到所有人信息
按Sort by email,能按email排序看到所有人信息
在下方的编辑框输入月份,能看到指定月份生日的人
按who birth recentlt,弹出如下窗口
选中联系人,按send a congralutions email弹出如下窗口
自动生成了祝贺信息,按send键发送。
在主界面下按search按钮,弹出如下窗口
支持多条件搜索,输入信息后按search键便能看到信息。在主界面下按contact按扭,弹出如下窗口
选中联系人之后:
按“call”能模拟向对方打电话
按send message或者send mail弹出如下窗口
自动生成了默认短信,可以按右方的模板来改变短信内容,或者直接输入短信,按send键发送。
五、总结、收获和体会
1.调试中遇到的问题及解决方案:
1.Cstring可以存储进txt文件里,而读出来的时候却不能读进Cstring变量
解决方法:先用string读取数据,然后通过c_str()把string转为Cstring 2.经常读出来的是空文件
解决方法:经检查,发现之前曾经以ofstream对象打开文件,而未关闭。在之前的位置添加close()函数即可
3.经常边界溢出,但由于代码过长很难发现在哪出错
解决方法:在代码之间插入messagebox来定位错误位置
4.edit control里面的字符不会换行,而且换行时按回车键变成了退出
解决方法:把edit conrol属性AUTO HSCrool设为True,Muttiline设为
true
5.不知道怎么进行父窗口和子窗口的多项数据传输
解决方法:用txt文件作为载体传递数据
6.用for(int i=0;i 解决方法:因为i是递增的,而列数是递减的,删一个少一个,后一半的删除 都是无效操作。把i弄为递减的即可 2.值得后人吸取的教训 1.一开始时,我以为“朋友”的额外数据是“认识时间”,结果花了好多功夫来在input对话框里验证“认识时间”的正确性,后来才发现是“认识地点 2.删除列表列时用了递增的循环,导致列删不完。动态的项目应该根据情况决定递减还是递增。 3.收获与心得体会 通过这次个人通讯管理系统设计,我对MFC、消息的机制有了进一步的了解。 这次程序设计让我体会到了面向对象的好处,明白了C++是一个很强大的语言。由于老师没讲过MFC,所以这些内容都要靠自学,这样锻炼了自己的自学、分 析和解决问题的能力,为今后的开发打下坚实的基础。同时也大大提高了我打 代码的速度和准确性。学习MFC途中,我还学会了上各种网站搜索,加了好多 个C++交流的QQ群向别人请教MFC,交流其他技术,这对我的学习模式来说是 一个改革,对我以后的发展大有裨益。