《程序设计基础课程设计》课题:“班级通讯录管理系统”【c语言 + 链表 + 文件】


课程设计报告 课程名称: 程序设计课程设计 课程设计题目: 班级通讯录管理系统 姓 名: 陈 道 争 系: 计算机系 专 业: 网络工程 年 级: 网络 081 班 学 号: 200810314021 指导教师: 王未央 职 称: 副教授 2011 年 4 月 2 日 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 2 -页 共 19 页 目 录 1 设计目的………………………………………………………………………3 2 设计题目及要求………………………………………………… … 3 3 设计算法分析………………………………………………………………3 3.1 模块调用层次图………………………………………………………3 3.2 核心算法描述………………………………………………………6 3 . 3 系统特点……………………………………………………… 8 4 程序代码………………………………………………………………………8 5 调试情况…………………………………………………………………………19 6 结论……………………………………………………………………………21 参考文献 ………………………………………………………………………21 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 3 -页 共 19 页 班级通讯录管理系统 1.设计目的 本课程设计的目的就是要通过一次集中的强化训练,使学生能及时巩固已学的知识,补 充未学的但又必要的内容。进行课程设计目的在于加深对程序设计基础中基础理论和基本知 识的理解,促进理论与实践的结合,进一步提高程序设计的能力。具体目的如下: 1.使学生更深入地理解和掌握该课程中的有关基本概念,程序设计思想和方法。 2.培养学生综合运用所学知识独立完成课题的能力。 3.培养学生勇于探索、严谨推理、实事求是、有错必改,用实践来检验理论,全方位 考虑问题等科学技术人员应具有的素质。 4.提高学生对工作认真负责、一丝不苟,对同学团结友爱,协作攻关的基本素质。 5.培养学生从资料文献、科学实验中获得知识的能力,提高学生从别人经验中找到解 决问题的新途径的悟性,初步培养工程意识和创新能力。 6.对学生掌握知识的深度、运用理论去处理问题的能力、实验能力、课程设计能力、 书面及口头表达能力进行考核。 2.设计题目及要求 【1】设计题目:班级通讯录管理系统 【2】要求 实现如下功能: 1)建立班级通讯录结构体(学号,姓名,性别,手机号码,QQ 号码,宿舍号,电子邮 箱,家庭地址等)。 2)班级通讯录信息的初始化。 3)班级通讯录信息的添加、修改、删除、查找。 4)班级通讯录信息的显示输出。 5)将通讯录信息保存为文件。 6)备份通讯录信息。 综合应用数组、指针、结构体、文件等,对该设计题目进行设计和实现。课程设计完成 后,提交课程设计报告。 3.设计算法分析 3.1 模块调用层次图 【1】变量描述 数组 char changeNumber[MAX_SIZE]; 作用:存放待修改的通讯录信息的学生学号。 char delNumber[MAX_SIZE]; 作用:存放待删除的通讯录信息的学生学号。 char findNumber[MAX_SIZE]; 作用:存放待查询的通讯录信息的学生学号。 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 4 -页 共 19 页 char outName[MAX_SIZE]; 作用:存放保存到本地电脑的.txt 文件的文件名(在 saveToPc 函数中定义)。 char source[MAX_SIZE]; 作用:存放源文件名(在 readFromPcOk 函数和 backUpFromPc 函数中有定义)。 char end[MAX_SIZE]; 作用:存放目标文件名(在 backUpFromPc 函数中有定义)。 结构体 班级通讯录结构体: struct student { char number[MAX_SIZE]; //学号 char name[MAX_SIZE]; //姓名 char sex[MAX_SIZE]; //性别 char phone[MAX_SIZE]; //手机号码 char qq[MAX_SIZE]; //QQ 号码 char dorm[MAX_SIZE]; //宿舍号 char email[MAX_SIZE]; //电子邮箱 char address[MAX_SIZE]; //家庭地址 struct student *next; //下一个节点的地址 }; 宏定义 #define MAX_SIZE 200 #define DAXUE "上海海事大学" #define BANJI "网络 08" #define MIMA "2008" 系统已定义的相关文件函数 FILE *fp; fp = fopen(文件名,使用文件方式); 功能:实现打开文件。 fclose(文件指针) 功能:实现关闭文件。 ch=fgetc(文件指针); 功能:从指定的文件读入一个字符。 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 5 -页 共 19 页 fputc(ch,文件指针); 功能:把一个字符写到磁盘文件上去。 fprintf(文件指针,格式字符串,输出表列) 功能:fprintf 函数与 printf 函数作用相仿,只是他的写对象不是终端也是磁盘文件。 fscanf(文件指针,格式字符串,输入表列); 功能:fscanf 函数与 scanf 函数作用相仿,只是他的读对象不是终端也是磁盘文件。 自定义函数 struct student *create(int *count) 功能:创建链表(即实现手动输入来初始化的功能)。 void changeNode(struct student *head,char number[MAX_SIZE]) 功能:修改节点(即实现修改通讯录的功能)。 struct student *delNode(struct student *head,char number[MAX_SIZE],int *count) 功能:删除一个节点(即实现删除通讯录的功能)。 struct student *searchByNumber(struct student *head, char number[MAX_SIZE]) 功能:查找节点(即实现查询通讯录的功能)。 struct student *insertBack(struct student *head,int *count) 功能:插入一个节点(即实现添加功能)。 void printLianBiao(struct student *head,int *count) 功能:打印链表的所有节点(即实现了显示输出的功能)。 void saveToPc(struct student *head, int *count) 功能:把内存中的通讯录信息保存到本地电脑的.txt 文件(即实现了保存的功能)。 void backUpFromPc() 功能:复制磁盘文件(即实现了备份的功能)。 struct student *readFromPcOk(int *sum) 功能:从磁盘文件中读取数据到内存(即实现了调入已有通讯录信息的功能)。 int uniqueOk(struct student *head, char number[MAX_SIZE]) 功能:对于整个链表来说,某个学号是否已经存在。 int uniqueYes(struct student *head, struct student *p) 功能:对于除了特定节点之外的整个链表来说,某个节点的学号是否已经存在(在修改 节点的时候用)。 void yanZhengOk(); 功能:身份验证。 void tiShi1() 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 6 -页 共 19 页 功能:一打开此软件的时候提示用户本软件的功能等信息。 void tiShi2() 功能:提示用户操作说明。 void findHelp() 功能:查询的时候的提示信息。 【2】系统模块调用层次图 3.2 核心算法描述(用伪代码描述) 【1】创建链表 begin /*算法开始*/ do { malloc() => p NULL => p->next 【2】删除节点 begin /*算法开始*/ { if head == NULL { print 通讯录为空 【3】插入节点 begin /*算法开始*/ malloc => p p->next=NULL if head==NULL { 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 7 -页 共 19 页 input p->number while the p->number in existence { input p->number } if p->number != 0 { input p->name input p->sex input p->phone input p->qq input p->dorm input p->email input p->address if head==NULL { p => head p => tail } else { p => tail->next p => tail } (*count)++ } else { if head==NULL { return head; } NULL => tail->next return head } }while 1 end /*算法结束*/ return NULL } else { head => p while p!=NULL and p->number not find { p => q p->next => p } if p == NULL { print 找不到 } else { if p == head { p->next => head } else { p->next => q->next } free p (*count)-- print 删除成功! } } return head } end /*算法结束*/ p => head p => tail } else { forq=head;q!=NULL; q=q->next { q => tail } p => tail->next p => tail } (*count)++ input p->number while p->number is 0 or p->number in existence { input p->number } input p->name input p->sex input p->phone input p->qq input p->dorm input p->email input p->address return head; } end /*算法结束*/ 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 8 -页 共 19 页 3.3 系统特点 【1】特点 (1)、首先,在进入软件时,要进行身份验证。只有验证信息都正确了才可以进入系统, 这保证的系统的安全性。 (2)、进入系统之后,会出现欢迎信息和操作帮助提示,而且每次操作完成后,都会实 时出现操作帮助提示信息,有利于用户进行下一步的操作,体现了本软件的人性化。 (3)、本系统实现了两种方式进行初始化通讯录。如果你原来没有通讯录,可以选择“手 动输入信息来初始化” ,如果你原来已经有保存了一个通讯录,则可以选择“调入已有通 讯录来初始化”,这样就省去了一条一条输入的麻烦,进一步体现了人性化的程序设计思想。 (4)、在“添加、修改通讯录”时,做到了各种情况的逻辑判断。使得添加或修改的同 学的学号不能为“0”而且通讯录里不存在的,这样才允许添加或修改记录。 (5)、本软件经过精心的输出显示的格式控制,使得用户看得更清晰、明了,方便了用 户的使用和操作。 (6)、本软件在充分完成课题要求的情况下,还附加了“备份”的功能。 【2】分工 我们共同完成的是:通讯录的学生结构体、身份验证、提示信息、操作帮助、信息的显 示等。本人在整个系统的设计过程,主要的任务是:文件的相关操作,即调入已有的通讯录、 通讯录的保存和备份,还有手动输入信息来初始化等模块。 在设计的过程中我们勇于探索、严谨推理、实事求是、有错必改,用实践来检验理论。 认真负责、一丝不苟,协作攻关终于比较完美的完成了此次课程设计。 4. 程序代码 【1】程序代码(限于篇幅只给出自己所分工的和重要的部分代码,并已附详细的注释) userDefined.h //自定义头文件(放宏定义、结构体和所有函数的声明) #ifndef USERDEFINED_H #define USERDEFINED_H #define MAX_SIZE 200 //宏定义 struct student //班级通讯录结构体 { char number[MAX_SIZE]; //学号 char name[MAX_SIZE]; //姓名 char sex[MAX_SIZE]; //性别 char phone[MAX_SIZE]; //手机号码 char qq[MAX_SIZE]; //QQ 号码 char dorm[MAX_SIZE]; //宿舍号 char email[MAX_SIZE]; //电子邮箱 char address[MAX_SIZE]; //家庭地址 struct student *next; }; //以下是程序所有函数的声明,在各个函数的源文件已经有详细说明了 void tiShi1(); void yanZhengOk(); 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 9 -页 共 19 页 void tiShi2(); void findHelp(); struct student *insertBack(struct student *head,int *count); void backUpFromPc(); void changeNode(struct student *head,char number[MAX_SIZE]); struct student *create(int *count); struct student *delNode(struct student *head,char number[MAX_SIZE], int *count); struct student *searchByNumber(struct student *head, char number[MAX_SIZE]); void printLianBiao(struct student *head,int *count); struct student *readFromPcOk(int *sum); void saveToPc(struct student *head, int *count); int uniqueOk(struct student *head, char number[MAX_SIZE]); int uniqueYes(struct student *head, struct student *p); #endif main.c //主源文件 //系统头文件 #include //标准输入输出头文件 eg:printf(); scanf(); FILE 结构体 #include //关于字符数组的函数定义的头文件 eg:strcmp(); #include //标准库头文件 eg:malloc(); free(); //自定义头文件(放宏定义、结构体和所有函数的声明) //就相当于一个“接口”,当编译的时候,userDefined.h 文件里的内容会全部显示在这里 #include"userDefined.h" void main(void)//主函数 { int sum=0 ; //记录通讯录的条数 struct student *lianBiaoTou=NULL; //链表头 struct student *fineResult; int n=600000000; //退出到软件关闭前的延迟 char changeNumber[MAX_SIZE]; //修改操作时的学号 char delNumber[MAX_SIZE]; //删除操作时的学号 char findNumber[MAX_SIZE]; //查询操作时的学号 char firstInput; //操作选择 tiShi1(); //软件的功能介绍 yanZhengOk(); //验证信息,在调试的时候,可以把这个注释了 tiShi2(); //操作提示 printf("请选择操作【班级通讯录管理系统】的方式!\n"); printf("温馨提示:第一次进入本系统,可选择“手动创建通讯录”或“调入已有的通讯录”,\n"); printf("但是切记不能选择“调入已有的通讯录”后,再选择“手动创建通讯录”!!\n\n"); printf("请选择操作种类->"); while(1) //程序一直运行着,直到用户选择“Q”退出程序 { scanf("%c",&firstInput); //接受用户的操作选择 if(firstInput == 'Q') //如果用户选择“Q”则退出软件 { printf("\n\n 欢迎光临【班级通讯录管理系统】^_^\n\n\n"); 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 10 -页 共 19 页 while(n--); //延时关闭 break; } else if(firstInput == '\n') //回车键处理:不打印任何东西 { printf(""); } else { switch(firstInput) //用 swith 分支处理用户的操作选择 { case 'A': printf("\n 创建【通讯录】^_^\n"); lianBiaoTou=create(&sum); printf("\n 创建班级通讯录成功!!!^_^\n"); printf("\n 你刚才输入的通讯录是:\n"); printLianBiao(lianBiaoTou,&sum); //显示创建后的通讯录 break; case 'B': printf("\n 调入【通讯录】^_^!\n\n"); lianBiaoTou=readFromPcOk(&sum); printf("\n"); break; case 'C': printf("\n 添加【通讯录】^_^!\n"); printf("\n 请输入一条通讯录的相关信息!\n"); lianBiaoTou=insertBack(lianBiaoTou,&sum); printf("\n 添加一条通讯录后的全部通讯录信息为:\n"); printLianBiao(lianBiaoTou,&sum); //显示添加后的通讯录 break; case 'D': printf("\n 修改【通讯录】^_^!\n"); printf("\n 请输入想要修改的通讯录的学生学号:"); scanf("%s",changeNumber); changeNode(lianBiaoTou,changeNumber); break; case 'E': printf("\n 删除【通讯录】^_^!\n"); printf("\n 请输入想删除的通讯录的学生学号:"); scanf("%s",delNumber); lianBiaoTou=delNode(lianBiaoTou,delNumber,&sum); break; case 'F': printf("\n 查询【通讯录】^_^!\n"); findHelp(); printf("\n 本程序仅提供【1】的查询方式\n"); 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 11 -页 共 19 页 printf("\n 请输入要查询的通讯录的学生学号->"); scanf("%s",findNumber); fineResult=searchByNumber(lianBiaoTou,findNumber); break; case 'G': printf("\n 最新的全部【通讯录】信息^_^!\n"); printLianBiao(lianBiaoTou,&sum); //显示通讯录 break; case 'H': printf("\n 保存【通讯录】为 txt 文件^_^!\n\n"); saveToPc(lianBiaoTou,&sum); break; case 'I': printf("\n 备份【通讯录】^_^!\n\n"); backUpFromPc(); break; default : //如果用户选择的都不是上面的功能,则提示操作选择有误 printf("\n 你选择的操作种类有误,请重新选择!!"); break; } tiShi2(); //操作提示 printf("请选择操作【班级通讯录管理系统】的方式!\n"); printf("温馨提示:第一次进入本系统,可选择“手动创建通讯录”或“调入已有的通讯录”, \n"); printf("但是切记不能选择“调入已有的通讯录”后,再选择“手动创建通讯录”!!\n\n"); printf("请选择操作种类->"); } } } create.c //头文件与 main.c 一样,限于篇幅在此省略 //此函数的功能:创建链表(即实现手动输入来初始化的功能)。 //参数:整形的指针变量,指向节点总个数。 //返回值:刚创建的链表头节点。 struct student *create(int *count) { struct student *head=NULL; //指向链表头节点 struct student *p=NULL; //指向创建的节点 struct student *tail=NULL; //指向链表尾节点 do { p=(struct student *)malloc(sizeof(struct student)); //为刚创建的节点申请一个 student 结构体类型大小的内存空间,并用 p 指针指向它。 p->next = NULL; //初始化 p 的 next 为空,防止指针乱指发生的错误。 printf("\n 请输入学号,学号为“0”即为保存并结束创建!\n"); 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 12 -页 共 19 页 printf("学号->"); scanf("%s",p->number); while(uniqueOk(head, p->number)==0) //循环判断想要创建的学号是否在链表中已经存在 { printf("\n 学号为 %s 的同学已经存在!\n",p->number); printf("\n 请重新输入想要创建的学生的信息!\n"); printf("学号->"); scanf("%s",p->number); } if(strcmp(p->number,"0")!=0) //学号不为“0”时 { printf("姓名->"); scanf("%s",p->name); printf("性别->"); scanf("%s",p->sex); printf("手机号码->"); scanf("%s",p->phone); printf("QQ 号码->"); scanf("%s",p->qq); printf("宿舍号->"); scanf("%s",p->dorm); printf("电子邮箱->"); scanf("%s",p->email); printf("家庭地址->"); scanf("%s",p->address); if(head==NULL) //如果刚创建的这个节点是这个链表的第一个节点,即在创建该 节点之前链表是空的 { //头指针和尾指针都指向该节点 head=p; tail=p; } else //如果刚创建的这个节点不是这个链表的第一个节点 { //下面两句的执行结果就是把 p 节点从链表的尾部插入链表 tail->next=p; tail=p; } (*count)++; //链表的节点数加一,即通讯录的条数加一 } else //学号为“0”时 { if(head==NULL) { return head; } tail->next=NULL; return head; } }while(1); } print.c //头文件与 main.c 一样,限于篇幅在此省略 //此函数的功能:打印链表的所有节点(即实现了显示输出的功能) //参数:链表头节点,节点个数 //返回值:空 void printLianBiao(struct student *head,int *count) { 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 13 -页 共 19 页 struct student *p=NULL; printf("\n\n★-☆-★-☆-★- 上 海 海 事 大 学 --- 网络 08--- 班 级 通 讯 录 -★-☆-★-☆-★ \n"); printf("\n 【总共有 %d 条记录】\n",*count); //输出节点个数 p=head; //p 指向头节点 printf("====================================\n"); printf("学号 姓名 性别 手机号码 QQ 号码 宿舍号 电子邮箱 家庭地址\n"); printf("====================================\n"); while(p!=NULL) //依次输出个节点 { printf("%-16s%-10s%-8s%-15s%-13s%-15s%-25s%-28s\n",p->number,p->name,p- >sex,p->phone,p->qq,p->dorm,p->email,p->address); printf("——————————————————————————————\n"); p=p->next; } } saveToPc.c //头文件与 main.c 一样,限于篇幅在此省略 //此函数的功能:把内存中的通讯录信息保存到本地电脑的.txt 文件(即实现了保存的功能) //参数:链表头节点,节点个数 //返回值:空 void saveToPc(struct student *head, int *count) { struct student *p=NULL; int i; FILE *outFilePointer=NULL; //声明 outFilePointer 为指向 FILE 类型结构体的指针变量 char outName[MAX_SIZE]; printf("请输入你想保存的文件路径包含文件名【形如:C:/111.txt】->"); scanf("%s",outName); //如果该文件不存在,则创建该文件 outFilePointer=fopen(outName,"w"); //用“只写”方式打开改文件,并用 outFilePointer 指向 要保持的文件 while(outFilePointer==NULL) //如果文件打开失败,则重新输入路径 { printf("\n 打开【%s】文件失败,请重新输入路径包含文件名【形如:C:/111.txt】 ->",outName); scanf("%s",outName); outFilePointer=fopen(outName,"w"); } //fprintf 函数与 printf 函数作用相仿,只是他的写对象不是终端也是磁盘文件, //函数原型:fprintf(文件指针,格式字符串,输出表列) fprintf(outFilePointer," ★-☆-★-☆-★-上海海事大学---网络 08---班级 通讯录-★-☆-★-☆-★ \n"); fprintf(outFilePointer,"\n 【总共有 %d 条记录】\n",*count); fprintf(outFilePointer,"====================================\n"); fprintf(outFilePointer,"学号 姓名 性别 手机号码 QQ 号码 宿舍号 电子邮箱 家庭地址\n"); fprintf(outFilePointer,"====================================\n"); p=head; //用 p 指向头节点 for(i=0;i<(*count);i++) //依次把内存中的节点数据写到 outFilePointer 指针所指的磁盘文件中 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 14 -页 共 19 页 { fprintf(outFilePointer,"%-16s%-10s%-8s%-15s%-13s%-15s%-25s%-28s\n",p->numb er,p->name,p->sex,p->phone,p->qq,p->dorm,p->email,p->address); fprintf(outFilePointer,"——————————————————————————————\n"); p=p->next; } fclose(outFilePointer); //关闭文件,防止它被误用,若关闭成功则返回 0,否则返回 EOF(-1) printf("\n\n 保存成功!请查看文件“%s”\n\n",outName); } readFromPc.c //头文件与 main.c 一样,限于篇幅在此省略 //此函数的功能:从磁盘文件中读取数据到内存(即实现了调入已有通讯录信息的功能) //参数:节点的总个数 //返回值:链表的头节点 struct student *readFromPcOk(int *sum) { FILE *sourceFile=NULL; //声明 sourceFile 为指向要读取数据的源文件的文件型指针变量 char source[MAX_SIZE]; //接受源文件的文件名 struct student *p=NULL,*q=NULL,*head=NULL,*k=NULL; int i; //for 循环计数变量 //下面声明的各个字符型数组用来存读入的相应信息 char biaoti[MAX_SIZE]; char tongji[MAX_SIZE]; int count; char tiaojilu[MAX_SIZE]; char shangtiao[MAX_SIZE]; char xueHao[MAX_SIZE],xingMing[MAX_SIZE],xingBie[MAX_SIZE],shouJiHao[MAX_SIZE],qqHa o[MAX_SIZE],suSheHao[MAX_SIZE],youXiang[MAX_SIZE],jiaTing[MAX_SIZE]; char zhongtiao[MAX_SIZE]; char xiatiao[MAX_SIZE]; printf("请输入你想调入的通讯录文件路径包含文件名【形如:C:/111.txt】->"); scanf("%s",source); sourceFile=fopen(source,"r"); //用“只读”方式打开改文件,并用 sourceFile 指向打开的文件 while(sourceFile==NULL) //如果文件打开失败,则重新输入路径 { printf("\n 打不开【%s】通讯录文件,请重新输入路径包含文件名【形如:C:/111.txt】 ->",source); scanf("%s",source); sourceFile=fopen(source,"r"); } printf("\n 调入【通讯录】成功!\n\n"); printf("文件【%s】中的内容是:\n\n\n",source); //fscanf 函数与 scanf 函数作用相仿,只是他的读对象不是终端也是磁盘文件, //函数原型:fscanf(文件指针,格式字符串,输入表列); fscanf(sourceFile,"%s",biaoti); fscanf(sourceFile,"%s",tongji); fscanf(sourceFile,"%d",&count); fscanf(sourceFile,"%s",tiaojilu); fscanf(sourceFile,"%s",shangtiao); fscanf(sourceFile,"%s",xueHao); fscanf(sourceFile,"%s",xingMing); fscanf(sourceFile,"%s",xingBie); fscanf(sourceFile,"%s",shouJiHao); fscanf(sourceFile,"%s",qqHao); 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 15 -页 共 19 页 fscanf(sourceFile,"%s",suSheHao); fscanf(sourceFile,"%s",youXiang); fscanf(sourceFile,"%s",jiaTing); fscanf(sourceFile,"%s",zhongtiao); *sum=count; for(i=0;i<=count-1;i++) { p=(struct student *)malloc(sizeof(struct student)); p->next=NULL; fscanf(sourceFile,"%s",p->number); fscanf(sourceFile,"%s",p->name); fscanf(sourceFile,"%s",p->sex); fscanf(sourceFile,"%s",p->phone); fscanf(sourceFile,"%s",p->qq); fscanf(sourceFile,"%s",p->dorm); fscanf(sourceFile,"%s",p->email); fscanf(sourceFile,"%s",p->address); fscanf(sourceFile,"%s",xiatiao); if(head == NULL) { head=p; q=p; } else { //下面两句就是把节点依次连接起来 q->next=p; q=p; } } //以下的代码就是把上面接收到的数据,打印出来。 printf(" %s\n\n\n",biaoti); printf(" %s",tongji); printf(" %d ",count); printf("%s\n",tiaojilu); printf("%s\n",shangtiao); printf("%-16s%-10s%-8s%-15s%-13s%-15s%-25s%-28s\n",xueHao,xingMing,xingBie,sh ouJiHao,qqHao,suSheHao,youXiang,jiaTing); printf("%s\n",zhongtiao); k=head; while(k!=NULL) { printf("%-16s%-10s%-8s%-15s%-13s%-15s%-25s%-28s\n",k->number,k->name,k- >sex,k->phone,k->qq,k->dorm,k->email,k->address); printf("%s\n",xiatiao); k=k->next; } fclose(sourceFile); //切记要关闭文件,否则会有内存读取错误的问题。 return head; } backup.c //头文件与 main.c 一样,限于篇幅在此省略 //此函数的功能:复制磁盘文件(即实现了备份的功能) //参数:空 //返回值:空 void backUpFromPc() { char source[MAX_SIZE],end[MAX_SIZE]; //声明源文件名和目标文件名 FILE *sourceFile=NULL, *endFile=NULL; //声明源文件指针和目标文件指针 char ch; 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 16 -页 共 19 页 printf("请输入源通讯录文件路径包含文件名【形如:C:/111.txt】->"); scanf("%s",source); sourceFile=fopen(source,"r"); printf("\n"); while(sourceFile==NULL) { printf("\n 打不开【%s 】通讯录文件,请重新输入路径包含文件名【形如:C:/111.txt】 ->",source); scanf("%s",source); sourceFile=fopen(source,"r"); printf("\n"); } printf("请输入目的通讯录文件路径包含文件名【形如:C:/111.txt】->"); scanf("%s",end); endFile=fopen(end,"w"); printf("\n"); while(endFile==NULL) { printf("\n 打不开【%s 】通讯录文件,请重新输入路径包含文件名【形如:C:/111.txt】 ->",end); scanf("%s",end); endFile=fopen(end,"w"); printf("\n"); } //fgetc 函数:从指定的文件读入一个字符, //调用形式:ch=fgetc(文件指针); 函数带回的一个字符赋值给 ch, //当函数遇到一个文件的结束标志 EOF(即-1) ,下面的 for 循环退出。 for(ch=fgetc(sourceFile);ch!=EOF;ch=fgetc(sourceFile)) { //fputc 函数:把一个字符写到磁盘文件上去, //调用形式:fputc(ch,文件指针);如果输出成功,则返回输出的字符;否则返回一个 EOF(即-1) fputc(ch,endFile); } fclose(sourceFile); fclose(endFile); printf("\n 成功备份通讯录文件!从【%s】到【%s】!\n",source,end); } 【2】程序执行结果(由于截图太大,可能会影响图片的清晰度) 首先进入系统之前要进行身份验证,执行结果如下图所示。 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 17 -页 共 19 页 [A]手动输入信息来初始化,执行结果如下图所示。 涉及隐私图略。 [B]调入已有通讯录来初始化,执行结果如下图所示。 涉及隐私图略。 [C]通讯录信息的添加,执行结果如下图所示。 涉及隐私图略。 [D]通讯录信息的修改,执行结果如下图所示。 涉及隐私图略。 [E]通讯录信息的删除,执行结果如下图所示。 涉及隐私图略。 [F]通讯录信息的查询,执行结果如下图所示。 涉及隐私图略。 [G]通讯录信息的显示输出,上面已经演示过了,在此不重复。 [H]将通讯录信息保存为文件,执行结果如下图所示。 保存成功后,到相应的目录下打开该文件,文件的内容如下图所示。 涉及隐私图略。 [I]备份通讯录,执行结果如下图所示。 备份成功后,打开备份的目标文件,如下图所示。 涉及隐私图略。 【3】结果的讨论 本系统经过不断的调试和修改,基本上是接近完美了,到目前还没有出现 BUG。限于篇 幅的原因,系统遇到的各种情况不便于都用截图来说明,因此就在这里用文字表述一下。 (1)、本软件限定通讯录里的学生的学号不能为“0”,也不能重复。因此在创建链表的时 候,如果输入的学号已经存在,软件会自动提示:此学号已经存在,请重新输入。直到输入 的学号在链表中没有存在才允许输入后面的信息。链表创建好了,如果要结束创建,在输入 学号的提示后面输入“0”就可以了。 (2)、在修改、添加节点的模块中也同样做了限制,学号不能为“0”,也不能重复。从而 实现了软件的健全性。 (3)、从上面的执行结果的截图中我们可以看到,每次操作完之后,系统会提示“操作帮 助”方便用户进入下一步的操作。 5.调试情况 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 18 -页 共 19 页 本次的课程设计虽然已经完美的完成了,但是在课程设计的过程中,还是遇到了各种问 题,不过在我们小组成员的协作下,还是克服了各种各样的问题,下面就几个比较典型的、 印象深刻的调试问题进行详细的说明。 (1)、在创建链表的时候,每次申请一个结构体大小的空间的时候,都要把该空间的下 个节点的地址赋值为“NULL”,否则会发生内存的错误。具体的代码如下: //为要创建的节点申请一个 student 结构体类型大小的内存空间,并用 p 指针指向它 p=(struct student *)malloc(sizeof(struct student)); //初始化 p 的 next 为空,防止指针乱指发生的错误。 p->next = NULL; (2)、在判断新输入的学号是否在链表中已经存在的是时候,分两种情况,即要写两个 函数。原先我们只写一个函数,后来发现不行。因为当你在创建链表的时候判断的是你想创 建的这个学生的学号与链表中现有的所有学生的学号是否有重复,而当你在修改和插入节点 的时候,判断的是你修改后或插入后的那个节点除外的所有节点是否有与你想修改的或想插 入的这个学号是否相同。具体的代码见下方: //此函数的功能:对于整个链表来说,某个学号是否已经存在 //参数:链表的头节点,学号。 返回值:若已经存在则返回 0,否则返回 1 int uniqueOk(struct student *head, char number[MAX_SIZE]) { struct student *t=NULL; if(head != NULL) { for(t=head;t!=NULL;t=t->next) { if(strcmp(t->number,number)==0) { return 0; } } } return 1; } //此函数的功能:对于除了特定节点之外的整个链表来说,某个节点的学号是否已经存在(在修改和插入 节点的时候用) 。参数:链表的头节点,特定的节点。返回值:若已经存在则返回 0,否则返回 1 int uniqueYes(struct student *head, struct student *p) { struct student *t=NULL; if(head != NULL) { for(t=head;t!=NULL;t=t->next) { if(t==p) { continue; //关键的区别就是这句。。。 } if(strcmp(t->number,p->number)==0) { 程序设计课程设计 班级通讯录管理 2011 年 4 月 2 日 第- 19 -页 共 19 页 return 0; } } } return 1; } (3)、在显示输出通讯录的时候,我们原先没有经过输入格式的控制,以至于排版不整 齐。后来学到了,格式的控制,即每一项都要左对齐并且控制其字符空间。 例如:printf(“%-10s”,p->name); 其中的“%-10s”表示这个“p->name”占用 10 个字 符的空间,并且按左对齐的方式显示。还有如果“%10s”表示按右对齐方式显示。 (4)、在操作文件的时候,一定要切记:使用完文件之后必须关闭该文件。如果不关闭 文件将会丢失数据,因为在向文件写数据时,是先将数据输出到缓冲区,待缓冲区充满后才 正式输出给文件。如果当数据未充满缓冲区而程序结束运行,就会将缓冲区中的数据丢失。 用 fclose 函数关闭文件,可以避免这个问题,它先把缓冲区中的数据输出到磁盘文件,然 后才释放文件指针变量。 6.结论 略。 参考文献 [1] 谭浩强 著. C 程序设计(第三版). 北京:清华大学出版社,2005 [2] Herbert Schildt 著. 戴健鹏 等译. 最新 C 语言精华(第三版). 电子工业出版社,1997 [3] 编程爱好者网站. http://www.programfan.com/ [4] eNet 网络学院. http://www.enet.com.cn/eschool/ [5] 全国最大中文 IT 社区 CSDN. http://www.csdn.net/
还剩18页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 15 金币 [ 分享pdf获得金币 ] 6 人已下载

下载pdf

pdf贡献者

cdztop

贡献于2012-02-08

下载需要 15 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf