自己做的一个用文件实现的通讯录管理系统,有增、删、改、查、显示、排序、统计、退出七个功能,联系人有姓名、年龄、学号、性别、所在院校、所在班级、联系方式、家庭电话、家庭住址和邮箱十个信息。
添加时和修改时有判断年龄是否符合、学号是否重复两个检验模块。删除和修改都是用一个临时文件保存不删除和不修改的联系人,然后把临时文件改为原来的名字。查找和显示遍历文件就好。排序有按学号升序和按学号降序两种方式,主要思想是将学号放入一个数组中,然后将数组排好序,再将学号排序到文件中。
然后各种功能模块都进行了封装。写这个主要是为了记录自己的学习成果,如有不足之处,请指正,一起学习,一起进步。以下是代码,有六百多行。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define head "姓名","年龄","学号","性别","学校","班级","联系电话","家庭电话","家庭地址","邮箱"
#define print p->pName,p->pAge,p->pId,p->pSex,p->pSchool,p->pClass,p->pSelfPhone,p->pFamilyPhone,p->pAddress,p->pE_mail
#define scan &p->pName,&p->pAge,&p->pId,&p->pSex,&p->pSchool,&p->pClass,&p->pSelfPhone,&p->pFamilyPhone,&p->pAddress,&p->pE_mail
#define file "C:\\Users\\Lenovo\\Desktop\\Person.txt"
#define fileTemp "C:\\Users\\Lenovo\\Desktop\\temp.txt"
#define formatPrint "%s\t%d\t%ld\t%s\t%s\t%s\t%s\t\t%s\t\t%s\t\t%s\n"
#define formatScan "%s\t%d\t%ld\t%s\t%s\t%s\t%s\t\t%s\t\t%s\t\t%s\n"
#define formatHead "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
struct Person; //通讯录结构体
void menu(); //菜单函数
void choose(); //选择函数
void add(); //添加联系人函数
void deleteFun(); //删除联系人函数
void deleteMenu(); //删除菜单函数
int deleteChoose(); //删除选择函数
void deleteIdOrName(int select); //选择学号或姓名删除联系人函数
void modify(); //修改联系人函数
void modifyMenu(); //修改菜单函数
Person *modifyChoose(int select,FILE *fp,Person *p); //修改选择函数
void modifyIdOrName(int select); //选择学号或姓名修改联系人函数
void search(); //查找联系人函数
void searchIdOrName(int select); //选择学号或姓名查询联系人函数
void show(); //显示联系人函数
void sort(); //排序联系人函数
void AscendingAndDescending(int select); //升序和降序联系人函数
void insertion_sort(long array[],int lenth,int select); //插入排序算法
void sum(); //统计联系人
void quit(); //退出函数
void clear(); //清空控制台函数
void open(FILE *fp);//文件打开失败函数
void close(FILE *fp);//文件关闭失败函数
int isEmpty(FILE *fp,Person *p,long id,char name[10]);//判断联系人是否存在
int isAge(); //判断联系人年龄是否合适函数
int isId(FILE *fp,Person *p); //判断联系人学号是否重复函数
void renameFile(FILE *fp,FILE *fpTemp,Person *p); //关闭、删除、重命名文件
void printFile(FILE *fp,Person *p,long id,char name[10]); //打印出查询的结果
struct Person{//通讯录结构体
char pName[10]; //姓名
char pSex[3]; //性别
char pAddress[30]; //家庭地址
char pSchool[30]; //所在院校
char pClass[30]; //所在班级
char pSelfPhone[20]; //联系方式
char pFamilyPhone[20]; //家庭电话
char pE_mail[20]; //邮箱
long pId; //学号
int pAge; //年龄
int pFlag; //判断标志
};
int main(void){//主函数
system("color f1"); //修改窗口的背景颜色和字体颜色
system("mode con cols=130");//修改窗口大小
while(true){ //用一个死循环
menu(); //调用菜单命令
choose(); //调用选择命令
}
return 0;
}
void menu(){//菜单函数
printf("\t\t *********************★通讯录管理系统★******************\n");
printf("\t\t * 1:添加联系人 *\n");
printf("\t\t * 2:删除联系人 *\n");
printf("\t\t * 3:修改联系人 *\n");
printf("\t\t * 4:查询联系人 *\n");
printf("\t\t * 5:查看联系人 *\n");
printf("\t\t * 6:排序联系人 *\n");
printf("\t\t * 7:统计联系人 *\n");
printf("\t\t * 8:退出通讯录 *\n");
printf("\t\t *********************************************************\n");
printf("请输入你的选择:");
}
void choose(){//选择函数
int select;
scanf("%d",&select);
switch(select){
case 1: add();break;//新建联系人
case 2: deleteFun();break;//删除联系人
case 3: modify();break;//修改联系人
case 4: search();break;//查找联系人
case 5: show();break;//显示联系人
case 6: sort();break;//排序联系人
case 7: sum();break;//统计联系人
case 8: quit();break;//退出通讯录系统
default: printf("输入有误\n");clear();
}
}
void add(){//添加联系人函数
FILE *fp=fopen(file,"ab+");//用追加二进制的方式读写文件
open(fp);//调用判断文件是否会打开失败函数
//因为后面要判断学号是否重复
//所以Person中的name、age和id会被覆盖
//所以用临时变量储存
char name[10];
int age;
long id;
Person *p = (Person*)malloc(sizeof(Person));//动态分配内存
printf("请输入姓名:"); scanf("%s",name);
printf("请输入年龄:"); age = isAge();//判断联系人年龄是否合适函数
printf("请输入学号:"); id = isId(fp,p);//判断联系人学号是否重复函数
strcpy(p->pName,name);
p->pAge=age;
p->pId=id;
printf("请输入性别:"); scanf("%s",&p->pSex);
printf("请输入学校:"); scanf("%s",&p->pSchool);
printf("请输入班级;"); scanf("%s",&p->pClass);
printf("请输入联系电话:"); scanf("%s",&p->pSelfPhone);
printf("请输入家庭电话:"); scanf("%s",&p->pFamilyPhone);
printf("请输入家庭地址:"); scanf("%s",&p->pAddress);
printf("请输入邮箱:"); scanf("%s",&p->pE_mail);
fseek(fp,0L,SEEK_END);//将文件指针定位到文件末尾
fprintf(fp,formatPrint,print);//输入文件
close(fp);//关闭文件
free(p);//释放Person指针
printf("新建成功!\n");
clear();//清空控制台函数
}
void deleteFun(){//删除联系人函数
int flag=1;
while(flag!=0){
deleteMenu();//调用删除菜单函数
flag = deleteChoose();//调用删除选择函数,返回值是0则结束
}
clear();
}
void deleteMenu(){//删除菜单函数
system("cls");
printf("\t\t ************************★删除信息★*********************\n");
printf("\t\t * 1.输入被删除人的学号 *\n");
printf("\t\t * 2.输入被删除人的姓名 *\n");
printf("\t\t * 3.返回上一级菜单 *\n");
printf("\t\t *********************************************************\n");
printf("请输入你的选择:");
}
int deleteChoose(){//删除选择函数
int select,flag=1;
scanf("%d",&select);
switch(select){
case 1:
case 2: deleteIdOrName(select);flag=1;break;//调用按学号或姓名删除联系人函数
case 3: flag = 0;break;
default: printf("输入有误!\n");clear();
}
return flag;
}
void deleteIdOrName(int select){//选择学号删除联系人函数
FILE *fp=fopen(file,"ab+");
FILE *fpTemp=fopen(fileTemp,"wb");//一个临时文件
open(fpTemp);
open(fp);
Person *p=(Person*)malloc(sizeof(Person));
long id;
char name[10];
if(select==1){
printf("请输入被删除人的学号:");
scanf("%d",&id);
}else {
printf("请输入被删除人的姓名:");
scanf("%s",name);
}
int flag = isEmpty(fp,p,id,name);//调用判断联系人是否存在函数
if(flag==0){
printf("该联系人不存在!\n");
clear();
return;
}
printFile(fp,p,id,name);
printf("是否确认删除?\n");
printf("1.是 2.否\n");
printf("请输入你的选择:");
while(true){
scanf("%d",&flag);
if(flag==1){
break;
}else if(flag==2){
return;
}else{
printf("输入有误,请重新输入:");
}
}
fseek(fp,0L,SEEK_SET);//将文件指针定位到开头
while(!feof(fp)){
fscanf(fp,formatScan,scan);
if(select==1&&p->pId!=id){//select==1是按学号删除,如果匹配到相同,
//则不存到临时文件中,达到删除联系人的目的
fprintf(fpTemp,formatPrint,print);
}
if(select==2&&strcmp(p->pName,name)!=0){//select==2是按姓名删除
fprintf(fpTemp,formatPrint,print);
}
}
renameFile(fp,fpTemp,p);
printf("删除成功!\n");
clear();
}
void modify(){//修改联系人函数
system("cls");
int flag=1;
while(flag!=0){
printf("\t\t ************************★修改信息★*********************\n");
printf("\t\t * 1.输入被修改人的学号 *\n");
printf("\t\t * 2.输入被修改人的姓名 *\n");
printf("\t\t * 3.返回上一级菜单 *\n");
printf("\t\t *********************************************************\n");
printf("请输入你的选择:");
int select;
scanf("%d",&select);
switch(select){
case 1:
case 2: modifyIdOrName(select);flag=1;break;
case 3: flag=0;break;
default: printf("输入有误!\n");
}
}
clear();
}
void modifyMenu(){//修改菜单函数
printf("\t\t *********************************************************\n");
printf("\t\t * 1:修改姓名 *\n");
printf("\t\t * 2:修改年龄 *\n");
printf("\t\t * 3:修改学号 *\n");
printf("\t\t * 4:修改性别 *\n");
printf("\t\t * 5:修改学校 *\n");
printf("\t\t * 6:修改班级 *\n");
printf("\t\t * 7:修改联系电话 *\n");
printf("\t\t * 8:修改家庭电话 *\n");
printf("\t\t * 9:修改家庭地址 *\n");
printf("\t\t * 10:修改邮箱 *\n");
printf("\t\t * 11:全部修改 *\n");
printf("\t\t * 12:返回 *\n");
printf("\t\t *********************************************************\n");
printf("请输入你的选择:");
}
Person *modifyChoose(int select,FILE *fp,Person *p){//修改选择函数
char name[10];
int age;
long id;
switch(select){
case 1: printf("请输入新的姓名:"); scanf("%s",p->pName); break;
case 2: printf("请输入新的年龄:"); age = isAge();p->pAge = age;break;
case 3: printf("请输入新的学号:"); id = isId(fp,p);p->pId = id;break;
case 4: printf("请输入新的性别:"); scanf("%s",p->pSex); break;
case 5: printf("请输入新的学校:"); scanf("%s",p->pSchool); break;
case 6: printf("请输入新的班级:"); scanf("%s",p->pClass); break;
case 7: printf("请输入新的联系电话:"); scanf("%s",p->pSelfPhone); break;
case 8: printf("请输入新的家庭电话:"); scanf("%s",p->pFamilyPhone);break;
case 9: printf("请输入新的家庭地址:"); scanf("%s",p->pAddress); break;
case 10: printf("请输入新的邮箱:"); scanf("%s",p->pE_mail); break;
case 11: {
printf("请输入新的姓名:"); scanf("%s",name);
printf("请输入新的年龄:"); age = isAge();
printf("请输入新的学号:"); id = isId(fp,p);
printf("请输入新的性别:"); scanf("%s",p->pSex);
printf("请输入新的学校:"); scanf("%s",p->pSchool);
printf("请输入新的班级:"); scanf("%s",p->pClass);
printf("请输入新的联系电话:"); scanf("%s",p->pSelfPhone);
printf("请输入新的家庭电话:"); scanf("%s",p->pFamilyPhone);
printf("请输入新的家庭地址:"); scanf("%s",p->pAddress);
printf("请输入新的邮箱:"); scanf("%s",p->pE_mail);
strcpy(p->pName,name);
p->pAge = age;
p->pId = id;
}break;
default: printf("输入错误,请重新输入:");
}
printf("是否确认修改?\n");
printf("1.是 2.否\n");
printf("请输入你的选择:");
while(true){
scanf("%d",&p->pFlag);
if(p->pFlag==1||p->pFlag==2){
break;
}else{
printf("输入错误,请重新输入:");
}
}
return p;
}
void modifyIdOrName(int select){//选择学号或姓名修改联系人函数
FILE *fp=fopen(file,"ab+");
FILE *fpTemp=fopen(fileTemp,"wb");
open(fpTemp);
open(fp);
Person *p=(Person*)malloc(sizeof(Person));
long id;
char name[10];
if(select==1){
printf("请输入被修改人的学号:");
scanf("%ld",&id);
}else {
printf("请输入被修改人的姓名:");
scanf("%s",name);
}
int flag = isEmpty(fp,p,id,name);
if(flag==0){
printf("该联系人不存在!\n");
clear();
return;
}
printFile(fp,p,id,name);
modifyMenu();//调用修改菜单函数
while(true){
scanf("%d",&select);
if(select>=1&&select<=12){
if(select==12){
clear();
return;
}
break;
}else{
printf("输入有误,请重新输入:");
}
}
fseek(fp,0L,SEEK_SET);
while(!feof(fp)){
fscanf(fp,formatScan,scan);
if(p->pId==id||strcmp(p->pName,name)==0){
p = modifyChoose(select,fp,p);
if(p->pFlag==2){//如果flag=2,则不修改联系人,并结束函数
return;
}
//将修改后的信息写入临时文件
fprintf(fpTemp,formatPrint,print);
}else{
fprintf(fpTemp,formatPrint,print);
}
}
renameFile(fp,fpTemp,p);
printf("修改成功!\n");
clear();
}
void search(){//查询联系人函数
int select,flag=1;
while(flag!=0){
system("cls");
printf("\t\t **********************★查询信息★***********************\n");
printf("\t\t * 1.输入被查询人的学号 *\n");
printf("\t\t * 2.输入被查询人的姓名 *\n");
printf("\t\t * 3.返回上一级菜单 *\n");
printf("\t\t *********************************************************\n");
printf("请输入你的选择:");
scanf("%d",&select);
switch(select){
case 1:
case 2: searchIdOrName(select);flag=1;break;
case 3: flag=0;break;
default: printf("输入有误,请重新输入:");
}
}
clear();
}
void searchIdOrName(int select){//选择学号或姓名修改联系人函数
FILE *fp = fopen(file,"r");
open(fp);
Person *p = (Person*)malloc(sizeof(Person));
long id=0;
char name[10]="";
if(select==1){
printf("请输入被查询人的学号:");
scanf("%ld",&id);
}else {
printf("请输入被查询人的姓名:");
scanf("%s",name);
}
int flag = isEmpty(fp,p,id,name);
if(flag==0){
printf("该联系人不存在!\n");
clear();
return;
}
printFile(fp,p,id,name);
close(fp);
free(p);
clear();
}
void show(){//显示联系人函数
FILE *fp=fopen(file,"r");
open(fp);
if(fp==NULL){
perror("文件不存在\n");
close(fp);
}
char ch = fgetc(fp);
if(ch==EOF){
printf("文件为空!\n");
return;
}
printf("所有联系人信息如下:\n");
printf(formatHead,head);
fseek(fp,0L,SEEK_SET);
char chTemp[1024];//一行一行读数据
while(!feof(fp)){
printf("%s",chTemp);
fgets(chTemp,1024,fp);
}
close(fp);
clear();
}
void sort(){//排序联系人函数
system("cls");
int select,flag=1;
while(flag!=0){
printf("\t\t *************************★排序信息★********************\n");
printf("\t\t * 1.按学号升序 *\n");
printf("\t\t * 2.按学号降序 *\n");
printf("\t\t * 3.返回上一级 *\n");
printf("\t\t *********************************************************\n");
printf("请输入你的选择:");
scanf("%d",&select);
switch(select){
case 1:
case 2: AscendingAndDescending(select);flag=1;break;
case 3: flag=0;break;
default: printf("输入有误,请重新输入:");
}
}
clear();
}
void AscendingAndDescending(int select){//升序和降序联系人函数
FILE *fp = fopen(file,"ab+");
FILE *fpTemp = fopen(fileTemp,"wb");
Person *p = (Person*)malloc(sizeof(Person));
int lenth=0;
while(!feof(fp)){//得到文件的行数,即联系人的数量
fscanf(fp,formatScan,scan);
lenth++;
}
fseek(fp,0L,SEEK_SET);
int count=0;
long array[lenth];
while(!feof(fp)){//将所有id号都放到数组中
fscanf(fp,formatScan,scan);
array[count]=p->pId;
count++;
}
//然后将数组进行排序
if(select==1){//升序
insertion_sort(array,lenth,select);
}else{//降序
insertion_sort(array,lenth,select);
}
//然后将数组的编号和id匹配,相同则放入文件中
count=0;
while(count<lenth){
fseek(fp,0L,SEEK_SET);
while(!feof(fp)){
fscanf(fp,formatScan,scan);
if(p->pId==array[count]){
fprintf(fpTemp,formatPrint,print);
count++;
}
}
}
renameFile(fp,fpTemp,p);
printf("排序成功!\n");
clear();
}
void insertion_sort(long array[],int lenth,int select){//插数排序算法
//升序
if(select==1){
for(int i=1;i<lenth;i++){
for(int j=i;j>0;j--){//从第二个跟第一个开始比
if(array[j]<array[j-1]){
//换值
long temp = array[j];
array[j] = array[j-1];
array[j-1] = temp;
}
}
}
}else{
//降序
for(int i=lenth-1;i>=0;i--){
for(int j=i;j<lenth;j++){//从倒数第二个跟倒数第一个开始比
if(array[j]<array[j+1]){
//换值
long temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
}
}
void sum(){
FILE *fp = fopen(file,"r");
Person *p = (Person*)malloc(sizeof(Person));
open(fp);
int lenth=0;
while(!feof(fp)){
fscanf(fp,formatScan,scan);
lenth++;
}
printf("总共有%d个联系人\n",lenth);
close(fp);
free(p);
clear();
}
void quit(){//退出函数
printf("欢迎下次使用!\n");
exit(0);
}
void open(FILE *fp){//文件打开失败函数
if(fp==NULL){//若文件不存在,则给提示并关闭文件和退出系统
perror("文件不存在\n");
close(fp);
}
}
void close(FILE *fp){//文件关闭失败函数
int flag = fclose(fp);
if(flag!=0){
perror("文件不存在\n");
exit(0);
}
}
void clear(){//清空控制台函数
system("pause");
system("cls");
}
int isEmpty(FILE *fp,Person *p,long id,char name[10]){//判断联系人是否存在
int flag=0;
while(!feof(fp)){
fscanf(fp,"%s\t%d\t%ld\t%s\t%s\t%s\t%s\t\t%s\t\t%s\t\t%s\n",scan);
if(p->pId==id||strcmp(p->pName,name)==0){
flag=1;
}
}
return flag;
}
int isAge(){//判断联系人年龄是否合适
int age;
while(true){
scanf("%d",&age);
if(age<0||age>120){
printf("输入的年龄有误,请重新输入:");
}else{
break;
}
}
return age;
}
int isId(FILE *fp,Person *p){//判断联系人学号是否重复
int id;
int flag=1;
while(flag!=0){
scanf("%ld",&id);
fseek(fp,0L,SEEK_SET);
while(!feof(fp)){
fscanf(fp,"%s\t%d\t%ld\t%s\t%s\t%s\t%s\t\t%s\t\t%s\t\t%s\n",scan);
if(id==p->pId){
printf("学号已重复,请重新输入:");
flag=1;
break;
}
flag=0;
}
}
return id;
}
void renameFile(FILE *fp,FILE *fpTemp,Person *p){//关闭、删除、重命名文件
close(fp);
close(fpTemp);
free(p);
remove(file);//删除文件
rename(fileTemp,file);//将临时文件名改为原名
}
void printFile(FILE *fp,Person *p,long id,char name[10]){//打印出查询的结果
fseek(fp,0L,SEEK_SET);//将文件指针定位到文件开头
while(!feof(fp)){
fscanf(fp,formatScan,scan);//读取文件,知道文件末尾
if(p->pId==id||strcmp(p->pName,name)==0){//判断到相同则输出
printf("该联系人信息如下:\n");
printf(formatHead,head);//打印表头
printf(formatPrint,print);//打印内容
break;
}
}
}