数据结构课程设计报告 手机个人通讯录信息管理系统正文终稿
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
东北大学信息科学与工程学院
数据结构课程设计报告
题目手机个人通讯录信息管理系统课题组长黄红清
课题组成员邢伟王帅
专业名称计算机科学与技术
班级计1307
指导教师杨雷
2015 年 1月
课程设计任务书
题目:
手机个人通讯录信息管理系统
问题描述:
对手机个人通讯录的创建和查询等信息管理作一个简单的模拟。
设计要求:
设计手机个人通讯录管理的模拟程序。
(1)采用顺序表或结构体链表存储结构。
(2)实现通讯录的创建、修改、插入、删除、分组等管理功能。
(3)实现通讯录的各种查询和统计功能。
(4)采用优化的查询和排序算法和实用的人机交互界面。
(5)其它完善性功能。
指导教师签字:
年月日
目录
1 课题概述 (4)
1.1 课题任务 (4)
1.2 课题原理 (4)
1.3 相关知识 (4)
2 需求分析 (5)
2.1 课题调研 (5)
2.2 用户需求分析 (5)
3 方案设计 (6)
3.1 总体功能设计 (6)
3.2 数据结构设计 (6)
3.3 函数原型设计 (8)
3.4 主算法设计 (9)
3.5 用户界面设计 (10)
4 方案实现 (11)
4.1 开发环境与工具 (11)
4.2 程序设计关键技术 (11)
4.3 个人设计实现(按组员分工)
4.3.1 黄红清设计实现 (11)
4.3.2 邢伟设计实现 (26)
4.3.3 王帅设计实现 (28)
5 测试与调试 (31)
5.1 个人测试(按组员分工) (32)
5.1.1 黄红清测试 (31)
5.1.2 邢伟测试 (31)
5.1.3 王帅测试 (31)
5.2 组装与系统测试 (32)
5.3 系统运行 (32)
6 课题总结 (38)
6.1 课题评价 (38)
6.2 团队协作 (38)
6.3 个人设计小结(按组员分工) (39)
6.3.1 黄红清设计小结 (39)
6.3.2 邢伟设计小结 (39)
6.3.3 王帅设计小结 (39)
7 附录A 课题任务分工 (40)
A-1 课题程序设计分工 (40)
A-2 课题报告分工 (43)
附录B 课题设计文档(光盘) (44)
B-1课程设计报告(电子版) (44)
B-2源程序代码(*.H,*.CPP) (44)
B-3工程与可执行文件) (44)
B-4屏幕演示录像文件(可选) (44)
附录C 用户操作手册(可选) (45)
C.1 运行环境说明 (45)
C.2 操作说明 (45)
1 课题概述
1.1 课题任务
【问题描述】
对手机个人通讯录的创建和查询等信息管理作一个简单的模拟。
【设计要求】
设计手机个人通讯录管理的模拟程序。
(1)采用顺序表或结构体链表存储结构。
(2)实现通讯录的创建、修改、插入、删除、分组等管理功能。
(3)实现通讯录的各种查询和统计功能。
(4)采用优化的查询和排序算法和实用的人机交互界面。
(5)其它完善性功能。
1.2 课题原理
利用数据结构中的顺序表或链表对手机通讯录的联系人信息进行存储,同时通过图形界面的设计制作对手机通讯录的各个功能进行模拟。
1.3相关知识
(1)顺序表或链表的基本结构;
(2)顺序表和链表的基本操作,如:插入、删除、查找;
(3)C++ MFC可视化程序设计的基本知识;
2 需求分析
2.1 课题调研
我们的课题是手机通讯录的模拟,我们对身边同学手机通讯录进行了基本的调查,发现这些通讯录的基本功能大致相同:
(1)均带有分组功能。
将联系人可以分为多个组存储。
(2)可以直观地展示各组联系人以及每个联系人的详细信息。
点击每个条目后,自动展开分组或者直接显示出联系人的详细信息。
(3)可以对分组进行修改、删除、添加等操作。
(4)可以对联系人进行添加、删除、修改、移动等操作。
(5)可以进行姓名和号码的查询。
(6)拥有人性化的操作界面。
所以我们便以此为设计目标,进行手机通讯录的模拟程序设计。
2.2 用户需求分析
如今手机越来越成为人们生活、学习和工作中不可缺少的一员,但其最基本的功能是通话,通讯录的存在是及其必要和重要的,一个合理的手机通讯录能够更方便地对用户进行服务,用户使用它可以更便捷地查找和添加联系人,修改其信息等等,因此需求十分巨大。
在计算机还未普及之前通讯管理都是由联系人采用名片,笔录手工记帐的方式来操作的.现在一般的通讯录管理都是采用计算机作为工具的实用的计算机通讯录管理程序来帮助人们进行更有效的通讯录信息管理。
通讯录管理系统是典型的信息管理系统,其开发主要包括后台数据库的建立和维护以及前端应用程序的开发两个方面。
要求应用程序功能完备,易使用等特点。
功能上,需要实现通讯录管理系统的基本功能,如课题调研中所述的功能。
性能上,应当考虑更多的更快捷的查找操作,保证程序的运行速度。
3 方案设计
3.1 总体功能设计
(1)新建联系人、新建组功能
(2)删除、编辑联系人和组的功能
(3)移动联系人到其他分组的功能
(4)按姓名查询联系人功能
(5)按号码查询联系人功能
(6)显示联系人和组的详细信息功能
(7)联系人数量、分组数的基本统计功能
(8)帮助功能
3.2 数据结构设计
为了方便文件存储操作,整个程序数据结构采用顺序表来设计。
class Contact//最基本单位为联系人类,其中有每个联系人的具体信息条目{
public:
Contact();
~Contact();
int Create(char *n, char *p, char *c, char *r);
char name[25];//姓名
char phonenumber[12];//号码
char city[25];//城市
char remark[MAX_REMARK];//备注
int numberofcalls;//通话次数
struct record{
struct date{
int year;
int month;
int day;
int hour;
int minute;
} date;//通话日期时间
struct talktime{
int minute;
int second;
} talktime;//通话时长
} record[MAX_RECORD];//通话记录
};
class Group//组类包含联系人类数组,每组包含一定数目的联系人
{
public:
Group();
~Group();
int Create(char *groupname);
int AddContact(char *n,char *p,char *c,char *r);
int SearchContactName(char *key);
int SearchContactPhonenumber(char *key);
int DeleteContact(int c);
void HeapAdjust(int s, int m);
int Order();
char name[MAX_GROUPNAME];//组名
int numberofmenber;//成员数
Contact contact[MAX_NUMBEROFMENBER];//联系人数组
};
class PhoneBook//通讯录类包含组数组,只有一个通讯录,其下包含多个组{
public:
PhoneBook();
~PhoneBook();
int AddGroup(char *groupname);
int SearchGroup(char *key);
int DeleteGroup(char *key);
int SearchContactName(char * key, int &g, int &c);
int SearchContactPhonenumber(char * key, int &g, int &c);
int DeleteContact(char *key);
int order();
int numberofgroup;//组数
Group group[MAX_NUMBEROFGROUP];//组数组
};
3.3 函数原型设计
Contact::Contact();//联系人类的构造函数
Contact::~Contact();//联系人类的析构函数
int Contact::Create(char *n, char *p, char *c, char *r);//联系人对象的创建函数
Group::Group();//组类的构造函数
Group::~Group();//组类的析构函数
int Group::Create(char *groupname);//组类的创建函数,创建一个组
int Group::AddContact(char *n, char *p, char *c, char *r);//当前组添加一个联系人
int Group::SearchContactName(char * key);//搜索当前组指定姓名的联系人int Group::SearchContactPhonenumber(char * key);//搜索当前组指定号码联系人
int Group::DeleteContact(int c);//删除当前组指定序号为c的联系人void Group::HeapAdjust( int s, int m); //HeapAdjust() sub-function int Group::Order();//当前组按联系人姓名堆排序函数
int PhoneBook::order();//当前通讯录下对组进行排序
PhoneBook::PhoneBook();//通讯录构造函数,包含读文件数据的操作PhoneBook::~PhoneBook();//通讯录析构函数,包含数据写入文件操作
int PhoneBook::AddGroup(char *groupname);//为当前通讯录添加一个组
int PhoneBook::SearchGroup(char *key);//在当前通讯录搜索指定组名
int PhoneBook::DeleteGroup(char *key);//删除当前通讯录中的指定组
int PhoneBook::SearchContactName(char * key, int &g, int &c);//在整个通讯录中搜索指定姓名的联系人,并将其组号和联系人号保存在g和c中
int PhoneBook::SearchContactPhonenumber(char * key, int &g, int &c);//在整个通讯录中搜索指定号码的联系人,并将其组号和联系人号保存在g和c 中
int PhoneBook::DeleteContact(char *key);//搜索通讯录中指定联系人并删除
void CPhoneBookDlg::UpdateTree();//更新Tree Control列表
void CPhoneBookDlg::OnBnClickedButton1();//新建组按钮
void CPhoneBookDlg::OnBnClickedButton2();//新建联系人按钮
void CPhoneBookDlg::OnCbnDropdownCombo1();//下拉列表选择框动态刷新void CPhoneBookDlg::OnBnClickedButton4();//删除联系人按钮
void CPhoneBookDlg::OnBnClickedButton5();//删除组按钮
void CPhoneBookDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult);//单击树控件中具体联系人或组显示对应信息
void CPhoneBookDlg::OnBnClickedButton3();//保存修改
void CPhoneBookDlg::OnBnClickedButton6();//编辑按钮
void CPhoneBookDlg::OnBnClickedButton7();//按姓名查询
void CPhoneBookDlg::OnBnClickedButton8();//按电话查询
void CPhoneBookDlg::OnBnClickedButton9();//关于
void CPhoneBookDlg::OnBnClickedButton10();//帮助
void CPhoneBookDlg::OnCbnDropdownCombo2();//动态刷新下方下拉列表
void CPhoneBookDlg::OnBnClickedButton11();//移动功能
void CPhoneBookDlg::OnBnClickedButton12();//删按钮功能
3.4 主算法设计
3.5 用户界面设计
说明:中央上方为通讯录显示区,右上侧为联系人信息显示区,其余部分为功能区,整个界面紧凑而不拥挤,方便用户的操作。
4 方案实现
4.1 开发环境与工具
采用VS2013进行C++编程与MFC可视化程序设计。
4.2 程序设计关键技术
(1)对顺序表的基本操作技术;
(2)折半查找技术;
(3)堆排序技术;
(4)MFC可视化程序开发技术;
(5)前端与后台的结合技术;
(6)联系人信息存储文件与读取文件技术;
4.3 个人设计实现(按组员分工)
4.3.1 黄红清设计实现
(1)我设计了由联系人到组、由组到通讯录的顺序表数据结构。
采用顺序表原因有二:其一,用户使用手机通讯录主要是为了查找和存储联系人信息,需要进行较多的查找操作,用顺序表效率更高;其二,顺序表存储到文件与从文件读取到顺序表的操作易于设计完成,简化了文件的存取操作。
整个结构示意图:
通讯录
组一组二组三
联系人一联
系
人
二
联
系
人
一
顺序表的结构实现:
class Contact
{
public:
Contact();
~Contact();
int Create(char *n, char *p, char *c, char *r);
char name[25];//姓名
char phonenumber[12];//号码
char city[25];//城市
char remark[MAX_REMARK];//备注
int numberofcalls;//通话次数
struct record{
struct date{
int year;
int month;
int day;
int hour;
int minute;
} date;//通话日期时间
struct talktime{
int minute;
int second;
} talktime;//通话时长
} record[MAX_RECORD];//通话记录
};
class Group
{
public:
Group();
~Group();
int Create(char *groupname);
int AddContact(char *n,char *p,char *c,char *r);
int SearchContactName(char *key);
int SearchContactPhonenumber(char *key);
int DeleteContact(int c);
void HeapAdjust(int s, int m);
int Order();
char name[MAX_GROUPNAME];//组名
int numberofmenber;//成员数
Contact contact[MAX_NUMBEROFMENBER];//联系人数组};
class PhoneBook
{
public:
PhoneBook();
~PhoneBook();
int AddGroup(char *groupname);
int SearchGroup(char *key);
int DeleteGroup(char *key);
int SearchContactName(char * key, int &g, int &c);
int SearchContactPhonenumber(char * key, int &g, int &c);
int DeleteContact(char *key);
int order();
int numberofgroup;//组数
Group group[MAX_NUMBEROFGROUP];//组数组
};
(2)我进行了程序的可视化界面设计,包括界面的分布美化、每个按钮、编辑框、下拉框、树框功能的实现,以及其他人性化功能的添加。
其间将所有后台函数进行必要的修改以适合MFC设计的需要,从而设计出人性化的图形界面,使程序更为直观地执行。
各个控件功能的实现:
void CPhoneBookDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
char groupname[MAX_GROUPNAME];
CEdit_groupname.GetWindowTextA(groupname, MAX_GROUPNAME);
if (groupname[0] != '\0')
{
if (phonebook.AddGroup(groupname))
{
phonebook.order();
CEdit_groupname.SetWindowTextA("");
UpdateTree();
MessageBox("新建组成功!");
}
else
MessageBox("组数已达上限!");
}
else
MessageBox("请输入组名!");
void CPhoneBookDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
char n[25], p[12], c[25], r[MAX_REMARK];
CEdit_n.GetWindowTextA(n, 25);
CEdit_p.GetWindowTextA(p, 12);
CEdit_c.GetWindowTextA(c, 25);
CEdit_r.GetWindowTextA(r, MAX_REMARK);
if (n[0] != '\0')
if (Combo1.GetCurSel() + 1 !=0)
if (phonebook.group[Combo1.GetCurSel() + 1].AddContact(n, p, c, r))
{
phonebook.group[Combo1.GetCurSel() + 1].Order();
CEdit_n.SetWindowTextA("");
CEdit_p.SetWindowTextA("");
CEdit_c.SetWindowTextA("");
CEdit_r.SetWindowTextA("");
UpdateTree();
MessageBox("新建联系人成功!");
}
else
MessageBox("该组联系人已满!");
else
MessageBox("请先选择一个组!");
else
MessageBox("请输入联系人姓名!");
}
void CPhoneBookDlg::OnCbnSelchangeCombo1()
{
// TODO: 在此添加控件通知处理程序代码
}
void CPhoneBookDlg::OnCbnDropdownCombo1()
{
// TODO: 在此添加控件通知处理程序代码
Combo1.ResetContent();
for (int i = 0; i < phonebook.numberofgroup; i++) Combo1.InsertString(i, phonebook.group[i+1].name); }
void CPhoneBookDlg::OnEnChangeEdit1()
{
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CDialogEx::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
}
void CPhoneBookDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
char key[25];
CEdit_delcontact.GetWindowTextA(key, 25);
if (key[0] != '\0')
if (phonebook.DeleteContact(key))
{
CEdit_sn.SetWindowTextA("");
CEdit_sp.SetWindowTextA("");
CEdit_sc.SetWindowTextA("");
CEdit_sr.SetWindowTextA("");
CEdit_sg.SetWindowTextA("");
CEdit_delcontact.SetWindowTextA("");
UpdateTree();
MessageBox("删除成功!");
}
else
MessageBox("没有找到该联系人!");
else
MessageBox("请输入要删除的联系人姓名!");
}
void CPhoneBookDlg::OnBnClickedButton5()
{
// TODO: 在此添加控件通知处理程序代码
char key[MAX_GROUPNAME];
CEdit_delgroup.GetWindowTextA(key, MAX_GROUPNAME);
if (key[0] != '\0')
{
if (phonebook.DeleteGroup(key))
{
CEdit_sn.SetWindowTextA("");
CEdit_sp.SetWindowTextA("");
CEdit_sc.SetWindowTextA("");
CEdit_sr.SetWindowTextA("");
CEdit_sg.SetWindowTextA("");
CEdit_delgroup.SetWindowTextA("");
UpdateTree();
Combo1.ResetContent();
for (int i = 0; i < phonebook.numberofgroup; i++)
Combo1.InsertString(i, phonebook.group[i + 1].name);
MessageBox("删除成功!");
}
else
MessageBox("没有找到该组!");
}
else
MessageBox("请输入要删除组的组名!");
}
void CPhoneBookDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
HTREEITEM child=Ctree.GetSelectedItem();
if (Ctree.GetParentItem(child)!=NULL)
{
char key[25];
int g, c;
strcpy_s(key, Ctree.GetItemText(child));
phonebook.SearchContactName(key, g, c);
CEdit_sn.SetWindowTextA(phonebook.group[g].contact[c].name);
CEdit_sp.SetWindowTextA(phonebook.group[g].contact[c].phonenumber );
CEdit_sc.SetWindowTextA(phonebook.group[g].contact[c].city);
CEdit_sr.SetWindowTextA(phonebook.group[g].contact[c].remark);
CEdit_sg.SetWindowTextA(phonebook.group[g].name);
CEdit_edit0.EnableWindow(1);
CEdit_editdel.EnableWindow(1);
}
else
{
char key[25], num[3], a[12] = { "该组共" }, c[3] = { "人" };
strcpy_s(key, Ctree.GetItemText(child));
int i = phonebook.SearchGroup(key);
_itoa_s(phonebook.group[i].numberofmenber, num, 10);
strcat_s(a, num);
strcat_s(a, c);
CEdit_sn.SetWindowTextA("");
CEdit_sp.SetWindowTextA("");
CEdit_sc.SetWindowTextA("");
CEdit_sg.SetWindowTextA(phonebook.group[i].name);
CEdit_sr.SetWindowTextA(a);
CEdit_edit0.EnableWindow(1);
CEdit_editdel.EnableWindow(0);
}
*pResult = 0;
}
//void CPhoneBookDlg::OnBnClickedButton3()
//{
// // TODO: 在此添加控件通知处理程序代码
// //
//}
void CPhoneBookDlg::OnBnClickedButton3()//edit save
{
// TODO: 在此添加控件通知处理程序代码
HTREEITEM child = Ctree.GetSelectedItem();
if (child != NULL&&Ctree.GetParentItem(child)!=NULL)
{
if (!Ctree.ItemHasChildren(child))
{
char key[25];
int g, c;
strcpy_s(key, Ctree.GetItemText(child));
phonebook.SearchContactName(key, g, c);
char gn[MAX_GROUPNAME], n[25];
CEdit_sg.GetWindowTextA(gn, MAX_GROUPNAME);
CEdit_sn.GetWindowTextA(n, 25);
if (gn[0] != '\0')
{
if (n[0] != '\0')
{
strcpy_s(phonebook.group[g].name, gn);
strcpy_s(phonebook.group[g].contact[c].name, n);
CEdit_sp.GetWindowTextA(phonebook.group[g].contact[c].phonenumber, 12);
CEdit_sc.GetWindowTextA(phonebook.group[g].contact[c].city, 25);
CEdit_sr.GetWindowTextA(phonebook.group[g].contact[c].remark, MAX_REMARK);
Ctree.SelectItem(NULL);
phonebook.group[g].Order();
phonebook.order();
CEdit_edit.EnableWindow(0);
CEdit_edit0.EnableWindow(0);
CEdit_editdel.EnableWindow(0);
CEdit_sn.EnableWindow(0);
CEdit_sp.EnableWindow(0);
CEdit_sc.EnableWindow(0);
CEdit_sr.EnableWindow(0);
CEdit_sg.EnableWindow(0);
UpdateTree();
}
else
MessageBox("请输入修改后的姓名!");
}
else
MessageBox("请输入修改后的组名!");
}
}
else
{
char key[25];
CEdit_sn.GetWindowTextA(key, 25);
if (strcmp(key, "") != 0)
{
int g, c;
if (!searchchoice)
phonebook.SearchContactName(beforeedit, g, c);
else
phonebook.SearchContactPhonenumber(beforeedit, g, c);
CEdit_sn.GetWindowTextA(phonebook.group[g].contact[c].name, 25);
CEdit_sp.GetWindowTextA(phonebook.group[g].contact[c].phonenumber, 12);
CEdit_sc.GetWindowTextA(phonebook.group[g].contact[c].city, 25);
CEdit_sr.GetWindowTextA(phonebook.group[g].contact[c].remark, MAX_REMARK);
CEdit_sg.GetWindowTextA(phonebook.group[g].name,
MAX_GROUPNAME);
Ctree.SelectItem(NULL);
phonebook.group[g].Order();
phonebook.order();
CEdit_edit.EnableWindow(0);
CEdit_edit0.EnableWindow(0);
CEdit_editdel.EnableWindow(0);
CEdit_sn.EnableWindow(0);
CEdit_sp.EnableWindow(0);
CEdit_sc.EnableWindow(0);
CEdit_sr.EnableWindow(0);
CEdit_sg.EnableWindow(0);
UpdateTree();
}
else
{
char n[25],ng[25];
strcpy_s(n,Ctree.GetItemText(child));
CEdit_sg.GetWindowTextA(ng, 25);
strcpy_s(phonebook.group[phonebook.SearchGroup(n)].name, ng);
Ctree.SelectItem(NULL);
phonebook.order();
CEdit_sg.EnableWindow(0);
CEdit_edit.EnableWindow(0);
CEdit_edit0.EnableWindow(0);
UpdateTree();
}
}
}
void CPhoneBookDlg::OnBnClickedButton6()//edit0
{
// TODO: 在此添加控件通知处理程序代码
char key[25];
CEdit_sn.GetWindowTextA(key, 25);
if (strcmp(key, "") != 0)
{
CEdit_sn.EnableWindow(1);
CEdit_sp.EnableWindow(1);
CEdit_sc.EnableWindow(1);
CEdit_sr.EnableWindow(1);
CEdit_sg.EnableWindow(1);
CEdit_edit.EnableWindow(1);
CEdit_editdel.EnableWindow(0);
}
else
{
CEdit_sg.EnableWindow(1);
CEdit_edit.EnableWindow(1);
CEdit_editdel.EnableWindow(0);
}
}
void CPhoneBookDlg::OnBnClickedButton7()
{
// TODO: 在此添加控件通知处理程序代码
char key[25];
int g, c;
CEdit_ckn.GetWindowTextA(key, 25);
strcpy_s(beforeedit, key);
searchchoice = 0;
if (phonebook.SearchContactName(key, g, c))
{
Ctree.SelectItem(NULL);
CEdit_sn.SetWindowTextA(phonebook.group[g].contact[c].name);
CEdit_sp.SetWindowTextA(phonebook.group[g].contact[c].phonenumber
);
CEdit_sc.SetWindowTextA(phonebook.group[g].contact[c].city);
CEdit_sr.SetWindowTextA(phonebook.group[g].contact[c].remark);
CEdit_sg.SetWindowTextA(phonebook.group[g].name);
CEdit_edit0.EnableWindow(1);
CEdit_editdel.EnableWindow(1);
}
else
{
Ctree.SelectItem(NULL);
CEdit_sn.SetWindowTextA("");
CEdit_sp.SetWindowTextA("");
CEdit_sc.SetWindowTextA("");
CEdit_sr.SetWindowTextA("");
CEdit_sg.SetWindowTextA("");
CEdit_ckn.SetWindowTextA("");
MessageBox("没有找到该联系人!");
}
}
void CPhoneBookDlg::OnBnClickedButton8()
{
// TODO: 在此添加控件通知处理程序代码
char key[25];
int g, c;
CEdit_ckp.GetWindowTextA(key, 25);
strcpy_s(beforeedit, key);
searchchoice = 1;
if (phonebook.SearchContactPhonenumber(key, g, c))
{
Ctree.SelectItem(NULL);
CEdit_sn.SetWindowTextA(phonebook.group[g].contact[c].name);
CEdit_sp.SetWindowTextA(phonebook.group[g].contact[c].phonenumber );
CEdit_sc.SetWindowTextA(phonebook.group[g].contact[c].city);
CEdit_sr.SetWindowTextA(phonebook.group[g].contact[c].remark);
CEdit_sg.SetWindowTextA(phonebook.group[g].name);
CEdit_edit0.EnableWindow(1);
CEdit_editdel.EnableWindow(1);
}
else
{
Ctree.SelectItem(NULL);
CEdit_sn.SetWindowTextA("");
CEdit_sp.SetWindowTextA("");
CEdit_sc.SetWindowTextA("");
CEdit_sr.SetWindowTextA("");
CEdit_sg.SetWindowTextA("");
CEdit_ckp.SetWindowTextA("");
MessageBox("没有找到该号码!");
}
}
//void CPhoneBookDlg::OnNMKillfocusTree1(NMHDR *pNMHDR, LRESULT *pResult)
//{
// // TODO: 在此添加控件通知处理程序代码
// //Ctree.SelectItem(NULL);
// *pResult = 0;
//}
void CPhoneBookDlg::OnBnClickedButton9()
{
// TODO: 在此添加控件通知处理程序代码
CAboutDlg dlg;
dlg.DoModal();
}
void CPhoneBookDlg::OnBnClickedButton10()
{
// TODO: 在此添加控件通知处理程序代码
MessageBox("使用帮助:\n1.第一次使用时,请先新建一个组;\n2.新建联系人时,须先选择分组;\n3.重名联系人请在姓名加以区分,如:张三1、张三2;\n如有其他问题,请Email:hhq1242400012@;");
}
void CPhoneBookDlg::OnEnChangeEdit16()
{
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CDialogEx::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
}
void CPhoneBookDlg::OnCbnDropdownCombo2()
{
// TODO: 在此添加控件通知处理程序代码
Combo2.ResetContent();
for (int i = 0; i < phonebook.numberofgroup; i++)
Combo2.InsertString(i, phonebook.group[i + 1].name);
}
void CPhoneBookDlg::OnBnClickedButton11()
{
// TODO: 在此添加控件通知处理程序代码
char key[25];
int g, c;
CEdit_move.GetWindowTextA(key, 25);
if (key[0] != '\0')
if (Combo2.GetCurSel() + 1 != 0)
{
if (phonebook.SearchContactName(key,g,c))
{
if (phonebook.group[Combo2.GetCurSel() + 1].AddContact(key,
phonebook.group[g].contact[c].phonenumber,
phonebook.group[g].contact[c].city,
phonebook.group[g].contact[c].remark))
{
phonebook.group[g].DeleteContact(c);
phonebook.group[Combo2.GetCurSel() + 1].Order();
UpdateTree();
MessageBox("移动成功!");
}
else
MessageBox("目标组已满!");
}
else
MessageBox("没有找到该联系人!");
}
else
MessageBox("请选择移动到的分组!");
else
MessageBox("请输入要移动的联系人!");
}
void CPhoneBookDlg::OnBnClickedButton12()
{
// TODO: 在此添加控件通知处理程序代码
char key[25];
CEdit_sn.GetWindowTextA(key, 25);
if (phonebook.DeleteContact(key))
{
MessageBox("删除成功!");
UpdateTree();
}
else
MessageBox("删除失败!");
Ctree.SelectItem(NULL);
CEdit_edit0.EnableWindow(0);
}
4.3.2 邢伟的设计实现
我设计了查找和排序功能,以及文件的操作功能,实现如下:
void Group::HeapAdjust( int s, int m) //HeapAdjust() sub-function {
int j;
Contact temp;
temp = contact[s];
for (j = 2 * s; j <= m; j *= 2)
{
if (j<m && strcmp(contact[j].name,contact[j + 1].name)<0) ++j;
if (!(strcmp(,contact[j].name)<0))
break;
contact[s] = contact[j];
s = j;
}
contact[s] = temp;
} //HeapAdjust() end
int Group::Order()
{
int i;
Contact temp;
for (i = numberofmenber / 2; i>0; --i)
HeapAdjust( i, numberofmenber);
for (i = numberofmenber; i>1; --i)
{
temp = contact[1];
contact[1] = contact[i];
contact[i] = temp;
HeapAdjust( 1, i - 1);
}
return 1;
}
int PhoneBook::order()
{
int i, j;
for (i = 2; i <= numberofgroup; ++i)
if (strcmp(group[i].name,group[i-1].name) <0)
{
group[0] = group[i];
for (j = i - 1;strcmp(group[0].name,group[j].name)<0 ; --j) group[j + 1] = group[j];
group[j + 1] = group[0];
}
return 1;
}
int PhoneBook::SearchGroup(char *key)
{
int mid, low = 1, high = numberofgroup;
while (low <= high)
{
mid = (low + high) / 2;
if (strcmp(key, group[mid].name) == 0)
{
return mid;
}
else if (strcmp(key, group[mid].name)<0)
high = mid - 1;
else
low = mid + 1;
}
return 0;
}
int PhoneBook::SearchContactName(char * key, int &g, int &c)
{
for (g = 1; g <= numberofgroup; g++)
if ((c = group[g].SearchContactName(key)) != 0)
{
return 1; break;
}
return 0;
}
int PhoneBook::SearchContactPhonenumber(char * key, int &g, int &c) {
for (g = 1; g <= numberofgroup; g++)
if ((c = group[g].SearchContactPhonenumber(key)) != 0)
{
return 1; break;
}
return 0;
}
PhoneBook::PhoneBook()
{
(*this).numberofgroup = 0;
ifstream is("phonebook.txt", ios_base::in);
is.read(reinterpret_cast<char*>(this), sizeof(PhoneBook));
is.close();
}
PhoneBook::~PhoneBook()
{
ofstream file("phonebook.txt", ios_base::out);
file.write(reinterpret_cast<char*>(this), sizeof(PhoneBook));
file.close();
}
4.3.3王帅的设计实现
我设计的是成员的的创建,添加,删除,组的创建,添加,删除,前序,后序,先序遍历。
树的销毁。
Contact::Contact(){ strcpy_s(remark, ""); numberofcalls = 0; record[0] = { { 2015, 1, 1, 15, 15 }, { 2, 30 } }; }
Contact::~Contact(){}
int Contact::Create(char *n, char *p, char *c, char *r)
{
strcpy_s(name, n);
strcpy_s(phonenumber,p);
strcpy_s(city, c);
strcpy_s(remark, r);
return 1;
}
Group::Group(){ numberofmenber = 0; }
Group::~Group(){}
int Group::Create(char *groupname)
{
strcpy_s(name, groupname);
numberofmenber = 0;
return 1;
}
int Group::AddContact(char *n, char *p, char *c, char *r) {
if (numberofmenber < MAX_NUMBEROFMENBER-1)
{
contact[numberofmenber + 1].Create(n, p, c, r);
numberofmenber++;
return 1;
}
else
return 0;
}
int Group::DeleteContact(int c)
{
Contact *p = &contact[c];
for (; c <= numberofmenber; c++)
{
*p = *(p + 1); p++;
}
numberofmenber--;
return 1;
}
int PhoneBook::AddGroup(char *groupname)
{
if (numberofgroup < MAX_NUMBEROFGROUP-1)
{
group[numberofgroup + 1].Create(groupname);
numberofgroup++;
return 1;
}
else
return 0;
}
int PhoneBook::DeleteGroup(char *key) {
int i;
if ((i = SearchGroup(key)) != 0)
{
Group *p = &group[i];
for (; i <= numberofgroup; i++)
{
*p = *(p + 1); p++;
}
numberofgroup--;
return 1;
}
else
return 0;
}
int PhoneBook::DeleteContact(char *key) {
int g, c;
if (SearchContactName(key, g, c))
return group[g].DeleteContact(c);
else
return 0;
}
5 测试与调试
5.1 个人测试(按组员分工)
5.1.1 黄红清测试
(1)测试了图形界面的执行情况,发现部分编辑框未输入内容时按钮仍然可以将空内容存入顺序表中,这是无意义的,于是对每个编辑框输入内容进行了判断,确保有输入时才会执行按钮功能。
(2)测试了Tree Control控件与详细信息展示区鼠标单击时一一对应功能,发现当鼠标点在某些联系人时,右边无法显示出相应信息,经调试,发现是由于联系人姓名为汉字或重复时,未对其进行排序,因此折半查找无法找到相应的联系人,于是进行了修改,每对联系人列表进行更改操作时,重新对其排序,以保证折半查找函数可以运行出正确的结果。
(3)在联系人列表下方添加了可以动态显示的联系人数目和分组数的统计。
(4)当鼠标点击组名时,发现右侧仍然显示上一个联系人的信息,于是对此进行了修改,使显示组名时,右边信息中可以显示组名,并且可以在备注栏中显示“该组共2人”的统计信息。
(5)利用删除联系人和添加联系人的基本功能,实现了将某联系人移动到另一分组的功能。
5.1.2邢伟测试
(1)测试了查找功能时,用的折半查找,但是局限于查找的关键字只有一个,如果想查找多条联系人信息,只能顺序查找。
(2)测试了排序功能,在phonebook里的查找,函数需要带入一个group 变量,所以定义了个全局变量。
5.1.3王帅测试
(1)顺序表的设计结构可以方便查找到需要删除的元素,进行删除时曾指针错误,进行调试,发现错误,并进行改正。
(2)测试时曾因组数和成员数在定义时过少,导致添加成员到上限时失败,找到后并进行改正。
5.2 组装与系统测试
操作名称操作流程操作结果和输出
打开通讯录双击exe程序打开通讯
录模拟系统
创建前台对话框和后台PhoneBook对
象,从文件读入通讯录数据,显示在
Tree Control树形控件中。
显示正确
新建联系人选择要加入的组,输入
至少姓名等联系人信
息,单击新建联系人按
钮
弹出成功对话框,联系人被添加至指定
组中,可以自行展开这组查询添加情
况。
添加正确
新建分组输入组名后,单击新建
分组按钮
弹出成功对话框,Tree Control控件
中显示出新增加的组名。
添加成功
测试详细信息显示在Tree Control中任
意单击组名或者联系
人名字
单击组名,详细信息显示出组名和该组
共多少人;单击联系人名字,显示出他
所在的组合他的具体信息。
显示正确
实时编辑、保存、删除操作在Tree Control中选
中联系人或组,或者在
查询功能搜索相应联
系人后,在详细信息显
示出对应信息,进行编
辑
选中组,则编辑后,只能修改组名;选
中联系人,编辑后,可以修改任何信息。
且单击保存后能正确保存。
修改无误。
当显示的是联系人信息时,才能进行删
除操作,点“删”按钮后,联系人成功
被删除。
而删除分组操作危险,故不可
以直接删除。
查询操作输入姓名或电话号进
行查询
输入姓名成功查询到该名字联系人信
息,输入电话号也成功查询到信息,皆
在详细信息区显示出来。
查询正确
删除操作输入联系人名字或输
入组名进行删除
弹出对话框,删除成功,则在Tree中
消失,删除失败则无改动。
移动操作输入联系人姓名,选择
要移动到的分组,单击
移动至按钮
从Tree Control中成功查询到联系人
已被移动至相应分组。
移动成功
帮助操作单击帮助按钮弹出对话框显示帮助信息
5.3 系统运行
在左侧新建选中组,输入联系人信息即可添加联系人:
下图为添加完成:
同样可以在组名中输入组名新建一个分组如“课题讨论组”。
下面将王阳移动到课题讨论组:
点击移动后:
下面是查询功能和即时编辑并保存功能:
同样也可以进行号码的查询。
输入组名可以删除一个组,如删除“课题讨论组”:
如图已不含“课题讨论组”。
帮助和关于:
6 课题总结
6.1 课题评价
通过组员们的辛苦设计,我们实现了通讯录的模拟功能,其中,除了最基本的创建、删除、修改联系人和组的功能外,额外实现移动联系人、数量统计、帮助以及具有动态显示的图形界面功能,圆满地完成了这次任务。
6.2 团队协作
整个程序分为前端和后台,后台主要由组员们进行设计,前端主要由组长设计。
设计前,我们共同讨论了应该采用的数据存储结构,结构相对应的功能函数,展开了一系列的编程。
组员热心地提供了图形界面MFC的视频教程,共同观看了教程,并且通过充分地讨论,学会了图形界面的设计。
组长进行了程序最终的整合,即时联系组员一起进行程序的调试分析,增强了程序的健壮性。
6.3 个人设计小结(按组员分工)
6.3.1 黄红清设计小结
(1)我设计了由联系人到组、由组到通讯录的顺序表数据结构。
采用顺序表原因有二:其一,用户使用手机通讯录主要是为了查找和存储联系人信息,需要进行较多的查找操作,用顺序表效率更高;其二,顺序表存储到文件与从文件读取到顺序表的操作易于设计完成,简化了文件的存取操作。
(2)我进行了程序的可视化界面设计,包括界面的分布美化、每个按钮、编辑框、下拉框、树框功能的实现,以及其他人性化功能的添加。
其间将所有后台函数进行必要的修改以适合MFC设计的需要,从而设计出人性化的图形界面,使程序更为直观地执行。
(3)在设计可视化界面的时候,对后台函数进行了必要的修改以使其能够与MFC设计相结合服务于图形界面,并且针对人性化的图形界面设计,添加了其他的功能如统计人数,组数、即时编辑,保存,删除、移动联系人等功能,完善了联系人显示框的显示功能,使其不仅能显示联系人详细信息,还能显示组的信息。
6.3.2邢伟设计小结
(1)将设计的从文件中打开数据和保存数据放在,phonebook类的构造函数与析构函数里,实现了方便的保存输出文件内容。
(2)对面向对象类编程有一定了解,可以实现封装,知道了面向对象对象的编程,容易分工并且实现代码重复利用。
(3)在写查找和排序功能时,认识到数据结构的重要性,可以大大提高程
序的效率。
6.3.3王帅设计小结
(1)删除成员时,开始删除联系人时需要对多个联系人进行移动,测试发现可以用对象指针对整个联系人进行移动,节省、提高效率,对组也是一样。
(2)实行实验设计时,用到许多遗忘的知识,如类,文件读取方面的c++语言知识,需要进行复习,加固理解。
7 附录A 课题任务分工
A-1 课题程序设计分工
学号姓名程序设计函数原型、类功能说明20133982 黄红清
20133982 黄红清class Contact;
class Group;
class PhoneBook;
void
CPhoneBookDlg::UpdateTre
e();
void
CPhoneBookDlg::OnBnClick
edButton1();
void
CPhoneBookDlg::OnBnClick
edButton2();
void
CPhoneBookDlg::OnCbnDrop
downCombo1();
void
CPhoneBookDlg::OnBnClick
edButton4();
void
CPhoneBookDlg::OnBnClick
edButton5();
void
CPhoneBookDlg::OnTvnSelc
hangedTree1(NMHDR
*pNMHDR, LRESULT
*pResult);
void
CPhoneBookDlg::OnBnClick
//联系人结构
//组结构
//通讯录结构
//更新Tree Control列
表
//新建组按钮
//新建联系人按钮
//下拉列表选择框动态
刷新
//删除联系人按钮
//删除组按钮
//单击树控件中具体
联系人或组显示对应信
息
//保存修改
edButton3();void
CPhoneBookDlg::OnBnClick edButton6();
void CPhoneBookDlg::OnBnClick edButton7();
void CPhoneBookDlg::OnBnClick edButton8();
void CPhoneBookDlg::OnBnClick edButton9();
void CPhoneBookDlg::OnBnClick edButton10();
void CPhoneBookDlg::OnCbnDrop downCombo2();
void CPhoneBookDlg::OnBnClick edButton11();
void CPhoneBookDlg::OnBnClick edButton12();//编辑按钮
//按姓名查询
//按电话查询
//关于
//帮助
//动态刷新下方下拉列表
//移动功能
//删按钮功能
20133994 邢伟void
Group::HeapAdjust( int s,
int m) //HeapAdjust()
sub-function
int Group::Order()
int PhoneBook::order()
int
PhoneBook::SearchGroup(c
har *key)
int
PhoneBook::SearchContact
//堆排序函数
//组内排序
//通讯录中的组排序
//按组名搜索组
//按联系人姓名搜索联
系人,并将其组号,序
Name(char * key, int &g, int &c)
int
PhoneBook::SearchContact Phonenumber(char * key, int &g, int &c)
PhoneBook::PhoneBook() PhoneBook::~PhoneBook() 号保存到g和c中
//按号码搜索联系人,并将其组号、序号保存到g和c中
//phonebook对象构造,从文件读出已有信息
//phonebook对象析构,将修改后的信息写入文件
20133990 王帅Contact::Contact()
Contact::~Contact()
int Contact::Create(char
*n, char *p, char *c, char
*r)
Group::Group()
Group::~Group()int
Group::Create(char
*groupname)
int
Group::AddContact(char
*n, char *p, char *c, char
*r)
int
Group::DeleteContact(int
c)
int
PhoneBook::AddGroup(char
*groupname)
int
PhoneBook::DeleteGroup(c
har *key)
//联系人构造函数
//联系人析构函数
//创建联系人
//组构造函数
//组析构函数
//创建组
//组内添加联系人
//组内删除序号为c的
联系人
//通讯录中添加组
//通讯录中删除组。