本章通过五个综合实例,展示C程序设计的高级应用,通过练习使用函数的声明、定义 与调用,要求读者掌握模块化程序设计的基本方法,能够综合利用所学知识,完成复杂的C 程序设计。 5.1 小型数据库实例1(通信录) #include<conio.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX 3 #define LEN sizeof(struct friend) struct friend { int num; /*编号*/ char name[8]; /*姓名*/ char telephone[13]; /*电话*/ char email[20]; /*E-mail 地址*/ char oicq[12]; /*oicq*/ char address[30]; /*住址*/ }friends[MAX]; void menu(); /*功能: 主菜单选择函数*/ void addfriend(); /*功能: 添加好友信息*/ void showall(); /*功能: 浏览并显示通信录所有好友信息*/ void delfriend(); /*功能: 根据姓名删除好友信息*/ void editfriend(); /*功能: 根据姓名修改好友信息*/ void menu_search(); /*功能: 查找菜单*/ void searchbyname(); /*功能: 按姓名查找好友信息*/ void searchbytel(); /*功能: 按电话号码查找好友信息*/ int jiemi(char *filename,char *psw); /*功能: 解密文件*/ void check(char filename[20]); /*检测文件是否需要解密*/ void jiami(char filename[20]); /*功能: 加密文件*/ void fun_quit(); /*功能: 检测退出时是否需要加密文件函数*/ void main() /*主函数*/ 88 { system("cls"); /*清屏*/ check("tongxl"); /*调用检测文件是否需要解密函数*/ menu(); /*调用主菜单*/ }v oid menu() /*功能: 主菜单选择函数*/ { char *menu[]={"#^#^#^#^#^#^#^通信录#^#^#^#^#^#^#^#", " a.添加好友信息", " b.删除好友信息", " c.修改好友信息", " d.查询好友信息", " e.显示所有好友信息", " f.退出", "#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#", " "}; /*定义菜单指针数组*/ int i; char sel; int quit=0; do { system("cls"); /*清屏*/ for(i=0;i<9;i++) /*输出显示菜单*/ printf("\n%s",menu[i]); printf("\n 请输入a,b,c,d,e 或f: \n"); sel=getchar(); switch(sel) { case 'a': addfriend();break; case 'b': delfriend();break; case 'c': editfriend();break; case 'd': menu_search();break; case 'e': showall();break; case 'f': quit=1;fun_quit(); } }while(!quit); }v oid addfriend() /*功能: 添加好友信息*/ { int total=0; /*用于存放已有好友人数*/ int x; FILE *fp; int i=0; struct friend *p_friend=friends; /*定义一指针p_friend 指向数组friends*/ struct friend friend_add; if((fp=fopen("tongxl","rb"))==NULL) / *打开文件*/ { printf("文件有错误不能打开!"); exit(0); }w hile(fread(p_friend,LEN,1,fp)) 89 /*将fp 所指文件的数据读入指针p_friend 所指的地址中,并统计好友人数*/ { p_friend++; total=total+1; }f close(fp); /*关闭文件*/ if(total==MAX) { printf("\n 通信录已满,无法再增加好友记录!"); system("pause"); menu(); }e lse { printf("\n=============================="); printf("\n 请输入好友的编号: "); scanf("%d",&friend_add.num); printf("\n 请输入好友的姓名: "); scanf("%s",friend_add.name); printf("\n 请输入好友的电话号码: "); scanf("%s",friend_add.telephone); printf("\n 请输入好友的email 地址: "); scanf("%s",friend_add.email); printf("\n 请输入好友的oicq 号码: "); scanf("%s",friend_add.oicq); printf("\n 请输入好友的住址: "); scanf("%s",friend_add.address); if((fp=fopen("tongxl","ab+"))==NULL) { printf("文件有错误不能打开!"); exit(0); }f seek(fp,LEN,SEEK_END); /*将文件指针移动到文件末尾*/ fwrite(&friend_add,LEN,1,fp); /*将添加的数据写入到fp 所指的文件中*/ fclose(fp); total=total+1; /*好友人数加1*/ printf("\n 增加好友记录成功!\n"); printf("\n 是否增加好友记录? 继续请按1,否则,请按0 返回主菜单"); scanf("%d",&x); while(x!=0&&x!=1) { printf("\n 提示: 您的输入有误,请重新输入0 或1!"); scanf("%d",&x); }i f(x==0) menu (); else addfriend(); } }void showall() /*功能: 浏览并显示通信录所有好友信息*/ { struct friend friend; 90 FILE *fp; int len; if((fp=fopen("tongxl","rb"))==NULL) / * 打 开 文 件*/ { printf("文件有错误不能打开!"); exit(0); }f seek(fp,0,SEEK_END); /*将指针fp 指向文件的末尾*/ len=ftell(fp); /*len 值为0 表示文件空,无须解密,否则需要密码后进入通信录系统*/ if(len==0) { printf("\n 通信录为空,没有信息可显示!"); printf("\n 按任意键返回主菜单\n"); getch(); menu(); }r ewind(fp); /*将fp 指向文件头*/ printf("\n 编号姓名 电话 email iocq 住址\n"); while(fread(&friend,LEN,1,fp)) printf("\n%3d%5s%10s%10s%10s%10s",friend.num,friend.name,friend.telephone, friend.email,friend.oicq,friend.address); fclose(fp); /*关闭文件*/ system("pause"); }v oid delfriend() /*功能: 按姓名删除好友*/ { struct friend *p_friend=friends; struct friend kong={0,""}; FILE *fp; int total=0; int i; int flag=0; /*标记通信录中是否存在要删除的好友,0 表示不存在,1 表示存在*/ char name_del[8]; /*要删除的好友的姓名*/ if((fp=fopen("tongxl","rb"))==NULL) { printf("文件有错误不能打开!"); exit(0); }w hile(fread(p_friend,LEN,1,fp)) { p_friend++; total++; }f close(fp); p_friend=friends; printf("\n 请输入要删除的好友的姓名: "); scanf("%s",name_del); for(i=0;i<total;i++) { if(strcmp(p_friend->name,name_del)==0) { p_friend[i]=friends[total-1]; 91 friends[total-1]=kong; flag=1; total=total-1; break; }e lse p_friend++; }i f(flag==0) { printf("\n 通信录中不存在该姓名的好友!\n"); system("pause"); return; }i f(flag==1) { if((fp=fopen("tongxl","wb+"))==NULL) { printf("文件有错误不能打开!"); exit(0); }p _friend=friends; for(i=0;i<total;i++) { fwrite(p_friend,LEN,1,fp); p_friend=p_friend+1; }f close(fp); printf("\n 成功删除该好友信息!\n"); system("pause"); menu(); } }v oid editfriend() /*功能: 修改好友信息*/ { struct friend *p_friend=friends; truct friend friend_edit; /*记录修改后的信息*/ FILE *fp; int total=0; int i; int locate; /*用于标记要修改信息的好友在文件中的位置*/ int flag=0; /*标记通信录中是否存在要修改信息的好友,0 表示不存在,1 表示存在*/ char name_edit[8]; /*要修改信息的好友的姓名*/ if((fp=fopen("tongxl","rb+"))==NULL) /*以r+方式打开,从而对文件进行修改*/ { printf("文件有错误不能打开!"); exit(0); }w hile(fread(p_friend,LEN,1,fp)) { p_friend++; total++; } 92 p_friend=friends; /*将指针p_friend 重新定位到数组friends 的首地址处*/ printf("\n 请输入要修改信息的好友的姓名: "); scanf("%s",name_edit); for(i=0;i<total;i++) { if(strcmp(p_friend->name,name_edit)==0) { locate=i; /*标记要修改信息的好友的位置*/ flag=1; break; }e lse p_friend++; }i f(flag==0) { printf("\n 通信录中不存在该姓名的好友!\n"); system("pause"); menu(); }i f(flag==1) { printf("\n=============================="); printf("\n 请输入好友的编号(原编号为%d): ",p_friend->num); scanf("%d",&friend_edit.num); printf("\n 请输入好友的姓名(原姓名为%s): ",p_friend->name); scanf("%s",friend_edit.name); printf("\n 请输入好友的电话号码(原电话号码为%s): ",p_friend->telephone); scanf("%s",friend_edit.telephone); printf("\n 请输入好友的email 地址(原email 地址为%s): ",p_friend->email); scanf("%s",friend_edit.email); printf("\n 请输入好友的oicq 号码(原oicq 号码为%s): ",p_friend->oicq); scanf("%s",friend_edit.oicq); printf("\n 请输入好友的住址(原住址为%s): ",p_friend->address); scanf("%s",friend_edit.address); fseek(fp,locate*LEN,SEEK_SET); /*将文件指针定位到文件中原信息的位置*/ fwrite(&friend_edit,LEN,1,fp); fclose(fp); printf("\n 成功修改该好友信息!!\n"); system("pause"); menu(); } }v oid menu_search() /*功能: 查询菜单*/ { int sel; system("cls"); { char *menu_search[]={"#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#", " 1.按姓名查找", " 2.按电话号码查找", "#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#", 93 " " }; int i; for(i=0;i<5;i++) printf("\n%s",menu_search[i]); printf("\n 请输入1 或2: \n"); scanf("%d",&sel); while(sel<1||sel>2) { printf("输入有误,请重新输入!\n"); printf("\n 请输入1 或2: \n"); scanf("%d",&sel); }s witch(sel) { case 1: searchbyname();break; case 2: searchbytel();break; } }v oid searchbyname() /*功能: 按姓名查找好友信息*/ { struct friend friend_search; /*记录查询到的信息*/ FILE *fp; int flag=0; /*标记通信录中是否存在要查询的好友,0 表示不存在,1 表示存在*/ char name_search[8]; /*要查询的好友的姓名*/ if((fp=fopen("tongxl","rb"))==NULL) / * 以只读方式打开的文件*/ { printf("文件有错误不能打开!"); exit(0); }p rintf("\n 请输入要修改查找的好友的姓名: "); scanf("%s",name_search); while(fread(&friend_search,LEN,1,fp)) if(strcmp(friend_search.name,name_search)==0) { flag=1; break; }f close(fp); if(flag==0) { printf("\n 通信录中不存在名字为%s 的好友!\n",name_search); system("pause"); menu(); }i f(flag==1) { printf("\n=============================="); printf("\n 查找成功!\n"); printf("姓名为%s 的好友的个人信息如下: \n",name_search); printf("\n 编号: %d",friend_search.num); printf("\n 电话号码: %s",friend_search.telephone); 94 printf("\nemail: %s",friend_search.email); printf("\noicq: %s",friend_search.oicq); printf("\n 住址: %s\n",friend_search.address); system("pause"); menu(); } }v oid searchbytel() /*功能: 按电话号码查找好友信息*/ { struct friend friend_search; /*记录查询到的信息*/ FILE *fp; int flag=0; /*标记通信录中是否存在要查询的好友,0 表示不存在,1 表示存在*/ char tel_search[13]; /*要查询信息的好友的电话号码*/ if((fp=fopen("tongxl","rb"))==NULL) /*以只读方式打开的文件*/ { printf("文件有错误不能打开!"); exit(0); }p rintf("\n 请输入要修改查找的电话号码: "); scanf("%s",tel_search); while(fread(&friend_search,LEN,1,fp)) if(strcmp(friend_search.telephone,tel_search)==0) { flag=1; break; }f close(fp); if(flag==0) { printf("\n 通信录中不存在电话号码为%s 的好友!\n",tel_search); system("pause"); menu(); }i f(flag==1) { printf("\n=============================="); printf("\n 查找成功!\n"); printf("电话号码为%s 的好友的个人信息如下: \n",tel_search); printf("\n 编号: %d",friend_search.num); printf("\n 姓名: %s",friend_search.name); printf("\nemail: %s",friend_search.email); printf("\noicq: %s",friend_search.oicq); printf("\n 住址: %s\n",friend_search.address); system("pause"); menu(); } }v oid fun_quit() { FILE *fp; int len; 95 if((fp=fopen("tongxl","rb"))==NULL) /*打开文件*/ { printf("文件有错误不能打开!"); exit(0); }f seek(fp,0,SEEK_END); /*将指针fp 指向文件的末尾*/ len=ftell(fp); /*值为0 表示文件为空,无需解密,否则需要解密后进入通信录系统*/ if(len==0) { printf("\n 文件为空,无需加密!\n 按任意键退出系统……"); exit(1); }e lse { jiami("tongxl"); exit(1); } }v oid check(char filename[20]) /*检测文件是否需要解密*/ { FILE *fp,*fp_psw; int len,i=0,j=0; int k=0; char ch; char psw[9],pswold[9]; if((fp=fopen(filename,"rb"))==NULL) /*以只读方式打开的文件*/ { printf("文件有错误不能打开!"); exit(0); }f seek(fp,0,SEEK_END); /*将指针fp 指向文件的末尾*/ len=ftell(fp); /*0 表示文件为空,无需解密,否则需要机密后进入通信录系统*/ if(len>0) {i f((fp_psw=fopen("password","rb"))==NULL) /*以只读方式打开密码文件*/ { printf("密码文件有错误不能打开!"); exit(0); }c h=fgetc(fp_psw); while(!feof(fp_psw)) /*从密码文件中读出原来原加密文件密码到pswold 中*/ { pswold[i++]=ch; ch=fgetc(fp_psw); }p swold[i]='\0'; printf("\n 文件已加密,需解密!\n 请输入密码: "); scanf("%s",psw); if(strcmp(psw,pswold)==0) { k=jiemi("tongxl",psw); /* 调 用解密函数*/ if(k==1) printf("\n 文件解密完成!\n 按任意键进入通信录系统!\n"); 96 else { printf("\n 文件解密没有完成!\n 按任意键退出通信录系统!\n"); getch(); exit(0); } } else { printf("\n 密码错误,无法继续操作,即将退出系统...\n"); system("pause"); exit(0); } }e lse printf("\n 原文件为空,无须解密!\n"); printf("\n 按任意键进入通信录!\n"); getch(); /*进入菜单调用*/ }i nt jiemi(char *filename,char *psw) /*功能: 解密函数*/ { FILE *fp1,*fp2; int len=0; int j=0; char ch; if((fp1=fopen(filename,"rb"))==NULL)/*以只读方式打开的文件*/ { printf("文件有错误不能打开!"); return 0; }i f((fp2=fopen("new","wb"))==NULL) { printf("文件有错误不能打开!"); return 0; }c h=getc(fp1); while(!feof(fp1)) /*将fp1 中数据与密码异或后写入fp2 文件中*/ { fputc(ch^psw[j>=len? j=0: j++],fp2); ch=getc(fp1); }f closeall(); /*关闭已打开的所有文件*/ remove(filename); /*删除加密前的文件*/ rename("new",filename); /*将文件"new"重命名为解密前的文件名*/ return 1; }v oid jiami(char *filename) /*功能: 加密函数*/ { char new_psw[9],ch; FILE *fp_psw,*fp; int i=0,j;