finish=clock();
return;
}
5.用结构search存储快速查找
bitnode*search(bitree&,char*);//查找
bitnode*search(bitree&T,charname[30])//查找返回节点
{
bitnode*p,*q;
if(T)
{
if(!
strcmp(T->a.name,name))
returnT;
p=search(T->lchild,name);
q=search(T->rchild,name);
if(p)returnp;
elsereturnq;
}
returnT;
}
6.根据家谱的特点,采用孩子-兄弟的二叉树链表表示法来实现,其中,各功能(如,统计任一家庭、结果的打印、屏幕显示、全屏可视化、支持鼠标等)操作,各类实现如下。
以下是各功能类型的数据成员基本操作
classbutton//鼠标点击类
{
public:
friendBOOLmouseclickr(HANDLEhOut,HANDLEhIn,button&a,INPUT_RECORDmouseRec);//鼠标右键单击事件
friendBOOLmouseclickl(HANDLEhOut,HANDLEhIn,button&a,INPUT_RECORDmouseRec);//鼠标左键单击事件
friendvoidmousemove(HANDLE,HANDLE,button&a,INPUT_RECORDmouseRec);
friendvoidmousemove1(HANDLE,HANDLE,button&a,INPUT_RECORDmouseRec);
friendBOOLmousedoubleclick(HANDLEhOut,HANDLEhIn,button&a,INPUT_RECORDmouseRec);//鼠标双击事件
COORDpos1;
voidcreatebutton(COORD,char*,WORD,WORD,HANDLE);//创建按钮
voidhidebutton(HANDLE,BOOL);//隐藏按钮或显示按钮
intlen;
BOOLp;//控制按钮是否可见
WORDatt1,att0;//att1按钮的颜色,att0鼠标移动到按钮上时按钮的颜色
charbuttonname[30];
};
BOOLfullScreen(BOOL,button,HANDLE,HANDLE);//全屏
voidsetmenu0(button*,int,HANDLE);//初始化菜单
voidsetmenu1(button*a,intn,HANDLEh);//设置菜单
BOOLframe1(HANDLE,HANDLE);//退出对话框
BOOLframe2(HANDLE,HANDLE,char*);//单按钮对话框
intframe3(HANDLE,HANDLE);//退出对话框
voidwindows1(HANDLE,HANDLE);家谱显示窗体1
voidwindows2(HANDLE,HANDLE,bitree&);家谱显示窗体2
bitnode*cinnode(bitnode*,HANDLE);//初始化时输入第一个节点
bitnode*cinnode1(bitnode*,HANDLE);//用于修改
voidxiugai(bitnode*,HANDLE);//修改功能
button*print1(bitree,button*,int,HANDLE);//打印家谱
bitnode*searchperson(HANDLE,bitree);//查询
voidclearscreen(HANDLE,COORD,COORD);//清空屏幕的一块区域
intdelfile(char*);//删除文件
bitreecreate(HANDLE,HANDLE);//初始化
voiddestroy(bitnode*);//销毁二叉树
voidsavefile(bitree&t);//保存文件
bitreeopenfile(HANDLE);//打开文件
voidstat(bitreet,double&age,float&stature,int&mannum,int&x,int&y,int&a,int&b);//统计函数统计平均年龄身高,男女比例
voidcoutxueli(inta);//输出统计后的学历
7.为使程序结构趋于清晰,分别使用dos下鼠标支持,window1(初如化后进入的界面1),window2(打开文件后的界面2),Create(创建新的家谱文件),insert(添加新成员),print(打印家谱),del(删除成员),savefile(文件的保存),openfile(文件的打开),统计家族情况将在下的功能介绍中得到相应的概述。
四.重要函数分析.
经上述的需求分析,及重要的数据类型进行描述后,开始对实现基本的几项功能,其中:
增加成员,修改成员资料,删除成员;数据的存取:
初始化数据,保存数据,读取数据;程序框架结构:
dos下界面形成,鼠标的应用等。
1.Dos下的鼠标应用功能
讲述上面基本功能前,首先,我们要实现如在Dos下应用鼠标操作,因为这是本课程设计的一个重要前提,而本程序设计则是应用到这个关键的策略。
本课程设计之前,我认为在DOS下应用鼠标是比较难以实现的事情,因为日常我们所见到在DOS下有鼠标的,应该是加载了某程序策略来加以实现,如GHOST软件。
现在可以借这次数据结构的课程设计来认识这个功能是如何实现的,经过网上资料搜集和查看相关的书籍。
最后应用到本课程设计中的部分策略如下:
#include
classbutton
{
public:
friendBOOLmouseclickr(HANDLEhOut,HANDLEhIn,button&a,INPUT_RECORDmouseRec);//鼠标右键单击事件
friendBOOLmouseclickl(HANDLEhOut,HANDLEhIn,button&a,INPUT_RECORDmouseRec);//鼠标左键单击事件
friendvoidmousemove(HANDLE,HANDLE,button&a,INPUT_RECORDmouseRec);
friendvoidmousemove1(HANDLE,HANDLE,button&a,INPUT_RECORDmouseRec);
friendBOOLmousedoubleclick(HANDLEhOut,HANDLEhIn,button&a,INPUT_RECORDmouseRec);//鼠标双击事件
COORDpos1;
voidcreatebutton(COORD,char*,WORD,WORD,HANDLE);//创建按钮
voidhidebutton(HANDLE,BOOL);//隐藏按钮或显示按钮
intlen;
BOOLp;//控制按钮是否可见
WORDatt1,att0;//att1按钮的颜色,att0鼠标移动到按钮上时按钮的颜色
charbuttonname[30];
};
BOOLmouseclickr(HANDLEhOut,HANDLEhIn,button&a,INPUT_RECORDmouseRec)//鼠标单击右键则返回true
{
if(a.p)
{
if(mouseRec.EventType==MOUSE_EVENT)
{
if(mouseRec.Event.MouseEvent.dwMousePosition.X>a.pos1.X&&mouseRec.Event.MouseEvent.dwMousePosition.X<=a.pos1.X+a.len&&mouseRec.Event.MouseEvent.dwMousePosition.Y==a.pos1.Y)
{
If(mouseRec.Event.MouseEvent.dwButtonState==RIGHTMOST_BUTTON_PRESSED)
{
if(mouseRec.EventType==MOUSE_EVENT)
{
if(mouseRec.Event.MouseEvent.dwMousePosition.X>a.pos1.X&&mouseRec.Event.MouseEvent.dwMousePosition.X<=a.pos1.X+a.len&&mouseRec.Event.MouseEvent.dwMousePosition.Y==a.pos1.Y)
{
if(mouseRec.Event.MouseEvent.dwButtonState==RIGHTMOST_BUTTON_PRESSED)
{
DWORDres;
ReadConsoleInput(hIn,&mouseRec,1,&res);
FillConsoleOutputAttribute(hOut,a.att1,a.len,a.pos1,NULL);
returntrue;
}
else
returnfalse;
}
elsereturnfalse;
}
elsereturnfalse;
}
else
returnfalse;
}
else
returnfalse;
}
else
returnfalse;
}
elsereturnfalse;
}
BOOLmouseclickl(HANDLEhOut,HANDLEhIn,button&a,INPUT_RECORDmouseRec)//鼠标单击左键则返回true
{
if(a.p)
{
………………………//省略部分代码段
BOOLmousedoubleclick(HANDLEhOut,HANDLEhIn,button&a,INPUT_RECORDmouseRec)//鼠标双击击按钮则返回true
{
if(a.p)
{
if(mouseRec.EventType==MOUSE_EVENT)
{
if(mouseRec.Event.MouseEvent.dwMousePosition.X>a.pos1.X&&mouseRec.Event.MouseEvent.dwMousePosition.X<=a.pos1.X+a.len&&mouseRec.Event.MouseEvent.dwMousePosition.Y==a.pos1.Y)
{
if(mouseRec.Event.MouseEvent.dwEventFlags==DOUBLE_CLICK)
{
FillConsoleOutputAttribute(hOut,a.att1,a.len,a.pos1,NULL);
returntrue;//
}
else
returnfalse;
}
else
returnfalse;
}
else
returnfalse;
}
elsereturnfalse;
}
在上述代码段的分析所知,本程序分别定义,鼠标的单击事件,双击事件,右键单击事件,左键单击事件,其中这让我体会最深刻的是,原来用C++语言在DOS下写一个鼠标事件是这么繁锁的事,因为我自己从事web程序开发,在WEB做鼠标事作,只要ONCLICk,doubleClick等提交javascript(自己设定的过程)就行了,根本就不用考虑编译器中已做的翻译.不过用C来实现,至少可以认识下如何在DOS下做操作的。
2.Dos下的界面显示
由于本程序设计是在Dos下运行,我们都知道,DOS下是没有图形界面的,因此,为了使界面美化及更人性化这个特点去出发,因此特意在本程序中应用到window类,其中在初始化进入前台时用voidwindows1(HANDLEhOut,HANDLEhIn)函数,显示出文件操作,方便调用保存好的家谱文件,同时,当经过windows1函数后,进入voidwindows2(HANDLEhOut,HANDLEhIn,bitree&t)函数窗口,这一步已经是打开了某个家谱文件后进入的窗口,初始化所有的基本功能及高极打印功能等。
其实在windows1函数是比较容易实现的事,只要调用相关的关键函数(如window类,button类[上面已分析],)基本可以实现,唯一是难于实现的是如果调用某家谱的文件呢?
这样涉及到文件的操作,其中更DEBUG调试出现了打开文件,提示有野指针的现象错误中提示到”DEBugAssertionFailed!
Dbgheap。
cexpression:
_CrtIsValidHeapPointer(pUserData)”经过相关的资料搜索,到现在DEBUG调试还没有得到答案,但是有replace调试中这个错误是被覆盖,但是这样不符合软件工程测试,希望老师能给出答案。
而关于windows2函数则是集成了本次程序设计的所有基本功能和高级功能在里面,这也是实现时间最长的一步,当中涉及到快速排序,栈的操作得的算法,知识的应用之广。
下面给出两个函数的部分代码。
voidwindows1(HANDLEhOut,HANDLEhIn)//操作窗口1
{
BOOLtal=true;
INPUT_RECORDmouseRec;
DWORDres;
hOut=GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出设备句柄
hIn=GetStdHandle(STD_INPUT_HANDLE);//获取标准输入设备句柄
CONSOLE_SCREEN_BUFFER_INFObInfo;//窗口缓冲区信息
GetConsoleScreenBufferInfo(hOut,&bInfo);//获取窗口缓冲区信息
COORDsize={600,600},posText={0,0};
SetConsoleScreenBufferSize(hOut,size);//重新设置缓冲区大小
SMALL_RECTrc={10,20,100,52};//重置窗口位置和大小
SetConsoleWindowInfo(hOut,true,&rc);
COORDp={1,1},poss={0,10},poss1={0,0},poss2={20,11};
COORDposa={40,5},pos1={10,15},posb={53,5},posc0={35,2};
COORDposc1={34,1},posc2={34,3},posc3={34,2},posc4={48,2};
FillConsoleOutputCharacter(hOut,'',bInfo.dwSize.X*bInfo.dwSize.Y-1,posText,NULL);
FillConsoleOutputAttribute(hOut,14,bInfo.dwSize.X*bInfo.dwSize.Y-1,posText,NULL);
SetConsoleTextAttribute(hOut,14);//设置窗口属性
SetConsoleCursorPosition(hOut,p);//设置光标的位置
………..//省