数据结构课程设计通讯录制作Word格式.docx
《数据结构课程设计通讯录制作Word格式.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计通讯录制作Word格式.docx(27页珍藏版)》请在冰点文库上搜索。
当操作完成通过文件件来存储链表的信息,下次打开程序时,读取文件里的内容到内存中,放在链表,然后又可以对链表进行操作;
在这里面,文件内容不可以在外部更改,只能通过读取到内存链表中,通过程序进行更改,然后再写入到文件,写入过程会覆盖上次的内容。
structaddress*start;
/*首结点*/
structaddress*last;
/*尾结点*/
structaddress*find(char*);
/*声明查找函数*/
voidenter();
/*函数声明*/
voidsearch();
/*查找,查找过程中调用find函数*/
voidsave();
/*存盘,将链表信息保存到文件中*/
voidload();
/*导入,将文件内容导入到内存链表中*/
voidlist();
/*显示当前链表中信息*/
voidddelete(structaddress**,structaddress**);
voidinsert(structaddress*i,structaddress**start,
structaddress**last);
voidinputs(char*,char*,int);
voiddisplay(structaddress*);
intmenu_select(void);
三.详细设计
1.主界面设计
通过switch语句调用各种函数,实现各种操作。
然后把switch嵌套到无限的for循环(for(;
;
))中,使完成每一步操作都回到到选择操作的主界面
main
menu_select
enter
ddelete
list
search
save
load
exit
inputs
insert
find
display
文件
函数之间的相互调用
voidmain()
{
start=last=NULL;
for(;
)/*无限循环*/
{
switch(menu_select())/*调用主界面的选择函数,带回返回值*/
case1:
enter();
continue;
case2:
ddelete(&
start,&
last);
case3:
list();
case4:
search();
case5:
save();
case6:
load();
case7:
exit(0);
}
intmenu_select(void)/*主目录*/
chars[80];
intc;
printf("
………………^欢迎使用DOS通讯录系统^………………\n"
);
************请在做其它操作前先导入*************\n"
***********************************************\n"
printf("
*****************1.输入信息******************\n"
printf("
*****************2.删除信息******************\n"
*****************3.显示信息******************\n"
*****************4.查找******************\n"
*****************5.存盘******************\n"
*****************6.导入******************\n"
*****************7.退出******************\n"
do{
\nPleaseenteryourchoice:
\n"
gets(s);
c=atoi(s);
/*将获取的字符串转换成整型*/
}while(c<
0||c>
7);
returnc;
/*返回输入值*/
2.输入信息函数
输入函数:
structaddress*info;
/*定义当前结点*/
for(;
)
info=(structaddress*)malloc(sizeof(structaddress));
/*为当前结点分配空间*/
if(!
info)
{
\nOutofmemory"
exit(0);
/*如果分配空间失败,退出程序*/
}
输入空姓名结束:
inputs("
请输入姓名:
"
info->
name,10);
info->
name[0])break;
/*如果输入姓名为空,结束循环*/
请输入街道:
street,50);
请输入城市:
city,15);
请输入国家:
state,15);
请输入邮编:
eip,7);
insert(info,&
/*调用结点插入函数*/
输入函数调用到另外两个函数,inputs和insert
其中inputs中还用到fgets(str,n,fp),把键盘的输入信息传到
字符串中
charp[255];
do
printf(prompt);
fgets(p,254,stdin);
/*stdin,标准输入缓存,获取键盘输入信息*/
if(strlen(p)>
count)
printf("
\nTooLong\n"
}while(strlen(p)>
count);
p[strlen(p)-1]=0;
strcpy(s,p);
insert是关键函数,每当输入完一条信息都会调用到insert函数,将信息插入到链表中
if(*last==NULL)/*如果尾结点为空,意味着当前链表为空*/
{/*则将该结点赋给头尾结点*/
i->
next=NULL;
i->
prior=NULL;
*last=i;
*start=i;
return;
else/*如果链表不为空,则将信息插入到链表尾,作为尾结点*/
{
(*last)->
next=i;
prior=*last;
i->
*last=(*last)->
next;
*last(*last)->
next
ii->
NULL
插入信息会显示在链表最后
3.删除·
查找·
显示函数
删除函数调用find函数,通过姓名,查找到该节点,然后删除该节点信息,这其中涉及到头尾节点,及其变化;
先判断是否为头结点,如果为头结点,则把原头结点的后继作为新的头结点
如果不为头结点,则该节点的前驱的next指向该节点的后继
如果该节点为尾结点,则让该节点的前驱作为新的尾结点
chars[80];
inputs("
s,10);
info=find(s);
if(info)
Deleting......\n"
if(*start==info)
*start=info->
if(*start)
(*start)->
else*last=NULL;
else
{info->
prior->
next=info->
if(info!
=*last)
next->
prior=info->
prior;
else
*last=info->
free(info);
-Ok,删除成功!
与删除相比,查找就简单的多,只需要调用find的函数,找到该节点记录并显示出来就行了,在search本身里面只要调整下输出的界面就行了
structaddress*find(char*name)/*查找函数,形参为欲查找结点的name域*/
info=start;
while(info)
if(!
strcmp(name,info->
name))
returninfo;
info=info->
Namenotfound.\n"
returnNULL;
输出函数更简单,直接输出链表即可
if(info==NULL)
当前记录为空!
else
姓名\t街道\t\t城市\t国家\t邮编\t\n"
while(info)
display(info);
/*display为输出节点函数,一些列print组成*/
if(info->
next==NULL)
{break;
}info=info->
};
4.存储与导入
存储
存储时通过fopen打开文件(没有该文件时则创建)
fp=fopen("
record.txt"
"
wb"
/*生成文件*/
fp)
{printf("
Cannotopenfile.\n"
return}
然后通过fwrite将链表信息写入文件
while(info)/*把链表写入文件*/
{fwrite(info,sizeof(structaddress),1,fp);
fwrite每次从info读取一个sizeof(structaddress)长度的数据,
写入fp文件中。
写入完毕后即关闭文件
fclose(fp);
导入
导入时先建立链表,为节点分配内存空间
然后打开文件,将文件的内容写入内存链表中
registerintt,size;
structaddress*info,*temp=0;
char*p;
FILE*fp;
/*打开文件*/
if((fp=fopen("
r"
))==NULL)
Cannotopenfile!
return;
}
\n\nLoading...\n"
/*调用文件*/
size=sizeof(structaddress);
/*为结点分配内存*/
start=(structaddress*)malloc(size);
start)/*如果读取失败,返回*/
Outofmemory!
info=start;
p=(char*)info;
while((*p++=getc(fp))!
=EOF)
for(t=0;
t<
size-1;
++t)
*p++=getc(fp);
info->
next=(structaddress*)malloc(size);
if(!
next)
return;
info->
prior=temp;
temp=info;
p=(char*)info;
temp->
next=0;
last=temp;
start->
prior=0;
注意:
每次文件存储的时候都会覆盖以前存在文件里的内容,而每次导入的时候都会改变链表的内容。
因此每次打开程序时请先导入存储在文件里的数据,或者将record.txt备份存储起来,避免数据丢失。
四.设计总结
通过本次课程设计,我学到了很多东西。
以前从没有用过文件方面的知识,而这次设计中用到了,刚开始使用时出了很多问题,在文件存储时经常遇到意外错误而导致程序终止了。
这次的实验使我对结构体,链表的认识更深刻,使用更熟练,刚开始时在链表插入时遇到好多次内存方面的错误,还有插入操作时对指针的使用不太熟练。
通过一次次的思考与实验,思路更加清晰,程序的容错能力也越来越强。
这次实验让我学到很多书本上没有的东西。
程序里多次用到for(;
)循环,还有(structaddress*)malloc(sizeof(structaddress))为节点分配内存空间。
在文件操作中主要涉及到的函数有:
fopen(”文件名”,”使用文件方式”);
fwrite(info,sizeof(structaddress),1,fp);
fclose(文件指针);
五.参考资料
C程序设计(第三版)谭浩强清华大学出版社
数据结构(C++版)李根强中国水利水电出版社
附完整源码:
#include<
stdio.h>
stdlib.h>
string.h>
/*函数声明*/
voidddelete(structaddress**start,structaddress**last);
switch(menu_select())
voidenter()/*输入函数,本函数循环输入资料,当输入姓名为空时退出*/
structaddress*info;
name[0])
break;
insert(info,&
voidinputs(char*prompt,char*s,intcount)/*输入函数,有越界检测功能*/
charp[255];
voidinsert(/*数据插入函数*/
structaddress*i,
structaddress**start,
structaddress**last
)
if(*last==NULL)/*如果尾结点为空,意味着当前链表为空*/
else
{
voidddelete(structaddress**start,structaddress**last)/*删除函数*/
/*输入欲删除结点的name域内容*/
info=find(s);
/*查找该内容*/
if(info)/*如果找到*/
if(*start==info)/*如果该结点为首结点,把该结点的下驱作为新的首结点(入口)*/
*start=info->
if(*start)
(*start)->
else*last=NULL;
else/*如果欲删除的结点不是首结点*/
/*令该结点的前驱的next指针指向该结点的后驱,
*又令该结点的后驱的prior指点指向该结点的前驱*/
if(info!
=*last)/*如果该结点是尾结点,则令该结点的前驱为尾结点*/
*last=info->
fre