一、课题任务人们在日常生活中经常要查找某个人或某个单位的电话号码,本实验将实现一个简单的个人电话号码查询系统,根据用户输入的信息(例如姓名等)进行快速查询二、设计要求(1)在外存上,用文件保存电话号码信息;(2)在内存中,设计数据结构存储电话号码信息;(3)提供查询功能:根据姓名或编号实现快速查询;(4)提供其他维护功能,例如插人、删除、修改等。
三、程序的结点设计现假设链表结点仅含有一个数据域和一个指针域。
数据域是为了描述通讯者的相关信息,定义通讯者的结点类型:typedef struct{char num[10]; //编号char name[15]; //姓名char phone[11]; //电话号码}dataType;因此,,线性表的链式存储结构定义如下:typedef struct node{ //结点类型定义dataType data; //结点的数据域struct node *next ; //结点指针域}listnode , * linklist ;linklist head ; //定义指向单链表的头指针listnode * p ; //定义一个指向结点的指针变量四、程序的功能设计创建:创建通讯录文件添加:添加通讯录记录输出:显示通讯录记录删除:删除通讯录记录查找:查询通讯录记录修改:修改通讯录记录保存:将信息保存到文件中五、程序的数据设计该系统用下面六个功能模块编写,每个模块执行不同的功能,体现了模块化设计的思想。
下面六个模块都是利用C语言文件,向文件中追加数据、修改数据、查询数据和删除数据。
建立:可以建立通讯录记录,利用C语言文件,向文件中按顺序输入编号、姓名、电话号码,这里实际上是要求建立一个带头结点的单链表。
添加:可以添加通信录记录,向链表中继续增加结点,但只是输入到内存中,如果要输入到文件中还得调用保存函数。
输出:也是用通过循环依次输出文件中的数据,即输出所有通讯录里的记录。
删除:输入你要删除的人的姓名或编号后,系统会自动删除他的记录,在删除通过switch语句满足提示你确认删除的功能,只有等你确认删除后才会删除。
查询:为了满足用户的实际需求,设计了两种查询方式,可以用姓名、编号两种方式查找通讯录记录。
这里用到strcmp()函数,通过比较字符串是否相同来判别是否找到相关信息,找到后,就把文件中的数据赋给对应的变量,再把变量所带的值输出到屏幕上。
修改:当你选择修改功能后,系统会在修改函数中调用查询函数来找到需要修改的记录,然后返回该记录的结点。
再通过printf语句来显示他的记录,再通过修改查询函数返回的结点来修改所需要修改的记录。
保存:用到fclose()函数,每次操作成功后会自动保存到指定的文件中。
六、程序的函数设计主函数和菜单选择函数部分:int main(){for( ; ; ){switch( menu_select() ){case 1:printf("\t\t\t建立\n\n");head = createlist();break;case 2:printf("\t\t\t添加\n\n");printf("编号姓名电话号码\n");p = ( linklist ) malloc ( sizeof ( listnode ) );scanf ( "%s%s%s" , p->data.num , p-> , p->data.phone ) ; insertnode(head,p);break;case 3:printf("\t\t\t查询\n\n");p = listfind( head );if(p!=NULL){printf("编号姓名电话号码 \n");printf("%s %s %s\n", p->data.num , p->, p->data.phone ); }elseprintf("没有查询到!\n");break;case 4:modify(head);printf("修改成功!\n");printf("请保存!\n");break;case 5:printf("\t\t\t删除\n\n");delnode(head);break;case 6:printf("\t\t\t输出\n\n");printlist(head);break;case 7:save(head);printf("保存成功!\n");system("pause");break;case 0:printf("\t\t\t亲爱的用户,白白了!我会想你的哦 >3<!!!\n\n"); return 0 ;}}return 0 ;}int menu_select(){int n;printf("\t\t\t**********************\n");printf("\t\t\t *********\n");printf ( "\t\t\t个人电话号码查询系统\n");printf ("\t\t\t<== 1 建立 ==>\n");printf ("\t\t\t<== 2 添加 ==>\n");printf ("\t\t\t<== 3 查询 ==>\n");printf ("\t\t\t<== 4 修改 ==>\n");printf ("\t\t\t<== 5 删除 ==>\n");printf ("\t\t\t<== 6 输出 ==>\n");printf ("\t\t\t<== 7 保存 ==>\n");printf ("\t\t\t<== 0 退出 ==>\n");printf ("\t\t\t<== 请选择 ==>\n");printf("\t\t\t *********\n");printf("\t\t\t**********************\n:");for(; ;){scanf ( "%d" , &n );if( n < 0 || n > 7 )printf ("输入错误,请重选:");else break;}return n;}上面主要是主函数和菜单选择函数程序部分,这部分是通过一个无限循环来执行上述所有的功能模块,(用for和switch语句解决),如果用户要退出的话,只需选择“0”就可以成功退出并且自动将数据保存到指定的文件中。
输入变量为n,它作为menu_selet函数的返回值提供给switch语句。
使用for循环实现重复选择,并在主函数中实现。
实际使用时,只有选择0—7才会有用,对于不符合要求的输入,提示输入错并要求重新输入。
创建模块:1..打开存储的文件,若成功打开,则读取已有信息。
2.若打开存储的文件失败,则自己建立一个文件,并且开始输入相应的信息。
建表表完成判断是继续还是离开。
3.打开存储的文件,若成功打开则,则读取已有信息。
4.若打开存储的文件失败,则自己建立一个文件,并且开始输入相应的信息。
建表表完成判断是继续还是离开。
linklist createlist(){linklist createlist(){ //建立if( ( fp = fopen(dir_name,"r") ) != NULL) { // 打开文件linklist head = ( linklist ) malloc ( sizeof ( listnode ) ) ; //动态建立空间listnode * p ,* rear;rear = head ;char a[30] , b[30] , c[30];fscanf( fp ,"%s%s%s\n",a,b,c); //读取"编号姓名电话号码" 这几个汉字while(!feof(fp)){ // 检测文件是否结束不是则继续循环,是则退出p = ( linklist ) malloc ( sizeof ( listnode ) );fscanf ( fp ,"%s%s%s\n",p->data .num ,p->data .name ,p->data .phone ); //读入信息进文档rear->next =p;rear=p;}rear->next =NULL;fclose(fp);printf("成功读取文件记录!\n");return head;}else{printf("不存在记录文件,请自己输入:\n") ;linklist head=( linklist ) malloc ( sizeof ( listnode ) );//申请新结//点listnode *p,*rear ;int flag=0; // 定义一个变量来判断是否循环rear=head;//尾指针初始指向头结点while(flag==0) {p =( linklist ) malloc ( sizeof ( listnode ) );printf("编号姓名电话号码\n");scanf ( "%s%s%s" , p->data.num , p-> , p->data.phone ) ;rear->next = p; // 新结点连结到尾结点之后rear = p; //尾指针指向新结点printf("按1结束建表,按0继续建表。
\n");printf("结束建表吗?(1/0):");scanf ( "%d" , &flag ); //读入一个标志数据}rear->next =NULL; //终端结点指针域置空return head; //返回链表头指}}在这个函数里,首先看文件是否存在,如果存在,就把信息从外存调到内存中来,如果不存在,就会提示不存在记录文件,请自己输入。