静态实现:http://blog.youkuaiyun.com/qq_29503203/article/details/51468830
动态实现:http://blog.youkuaiyun.com/qq_29503203/article/details/51469189
之前我们用静态和动态的方法来实现这个通讯录它存在着一个很明显的缺陷就是在信息不能被保存,显然在实际中它们很不实用。所以呢,这次我们来实现文件版本的形式加以改善。为了结构清晰我使用了三个文件来进行封装,Contact.h封装结构体以及函数的声明,test.c封装主函数,Contact.c用来封装函数的算法。
这里需要熟悉一些文件操作,比如文件指针,fopen,fread和fwrite函数的使用,接下来我们来了解一下它们:
(1)
fopen 它的函数原型为:FILE*fopen(const char *filename,const char *mode) ;filename:创建文件的名字;mode:允许进入文件的类型;简单来说这个文件的作用就是打开一个文件流;与fclose关闭文件流配套使用.
这里在使用文件指针的时候FILE一定要大写哦,我就犯过这样一次低级错误!!!
(2) perror: 它的函数原型为:void perror(const char * string) ;这是一种报告文件错误的函数,后面包括一个分号和一个空格,然后打印出一条用于解释当前错误代码的信息;当检测到一条致命的错误可用exit函数终止程序.
(3) fwrite: 它的函数原型为:size_t fwrite(const void *buffer, size_t size , size_t count , FILE*stream) ;buffer:数据写入的缓冲区;size:你要写入数据的字节数;count:被写入数据的最大个数;stream:目标文件指针;
fread和fwrite是类似的size_t fwrite(void *buffer, size_t size , size_t count , FILE*stream) ;
还值得注意的是加载文件函数在初始化后就可以调用了,而保存函数在退出时调用(退出并保存).在创建文件的时候可以在编译器的打开文件里进行创建就ok!再补充一点创建此文件是需要显示文件后缀,那么如何显示呢?我们可进入“我的电脑”,再点击“查看”,然后勾选“文件扩展名”,这样就好啦!!!
Contact.h
#ifndef __CONTACT_H__ //防止被重定义
#define __CONTACT_H__
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
enum OP
{
EXIT,
ADD,
DEL,
MODIFY,
SEARCH,
DISPLAY,
SORT,
CLEAR
};
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 25
#define MAX 1000
#define DEFAULT_SZ 2
#define DEFAULT_INC 2
typedef struct PerInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PerInfo;
typedef struct Contact
{
PerInfo *data;
int size;
int capacity; //电话本容量
}Contact,*Pcon;
void init_contact(Pcon pcon);
void _add_contact(Pcon pcon);
void _display_contact(Pcon pcon);
void _del_contact(Pcon pcon);
void _search_contact(Pcon pcon);
void _modify_contact(Pcon pcon);
void _sort_contact(Pcon pcon);
void _clear_contact(Pcon pcon);
void _save_contact(Pcon pcon);
void _load_contact(Pcon pcon);
#endif
Test.c
#include "Contact.h"
void menu()
{
printf("***** 1.add 2.del ****\n");
printf("***** 3.modify 4.search ****\n");
printf("***** 5.display 6.sort ****\n");
printf("***** 7.clear 0.exit ****\n");
}
int main()
{
Contact con;
int input = 1;
init_contact(&con);
while(input)
{
menu();
printf("请选择>:");
scanf("%d",&input);
switch(input)
{
case ADD:
_add_contact(&con);
break;
case DEL:
_del_contact(&con);
break;
case SEARCH:
_search_contact(&con);
break;
case MODIFY:
_modify_contact(&con);
break;
case DISPLAY:
_display_contact(&con);
break;
case SORT:
_sort_contact(&con);
break;
case CLEAR:
_clear_contact(&con);
break;
case EXIT:
_save_contact(&con);
free(con.data);
break;
default:
printf("选择错误\n");
break;
}
}
system("pause");
return 0;
}
Contact.c
#include"Contact.h"
void init_contact(Pcon pcon) //进行初始化
{
pcon->data=(PerInfo *)malloc(DEFAULT_SZ*sizeof(PerInfo));
pcon->size = 0;
pcon->capacity=DEFAULT_SZ;
if(pcon->data==NULL)
{
printf("out of memory");
exit(EXIT);
}
memset(pcon->data, 0,DEFAULT_SZ*sizeof(PerInfo) );
_load_contact(pcon);
}
static int find(Pcon pcon,char arr[])
{
int i=0;
for(i=0;i<pcon->size;i++)
{
if(strcmp(pcon->data[i].name,arr)==0)
return i;
}
return -1;
}
void check_capacity(Pcon pcon)
{
PerInfo *tmp=NULL;
while(pcon->size==pcon->capacity)
{
tmp=(PerInfo *)realloc(pcon->data,(pcon->capacity+DEFAULT_INC)*sizeof(PerInfo));
if(tmp==NULL)
{
printf("out of memory");
exit(EXIT);
}
else
{
pcon->data=tmp;
pcon->capacity+=DEFAULT_INC;
}
}
}
void _add_contact(Pcon pcon)
{
check_capacity(pcon) ;
printf("准备添加一个新成员!\n");
printf("请输入姓名:");
scanf("%s",pcon->data[pcon->size].name);
printf("请输入性别:");
scanf("%s",pcon->data[pcon->size].sex);
printf("请输入年龄:");
scanf("%d",&(pcon->data[pcon->size].age));
printf("请输入住址:");
scanf("%s",pcon->data[pcon->size].addr);
printf("请输入联系人电话:");
scanf("%s",pcon->data[pcon->size].tele);
printf("添加成功!\n");
(pcon->size)++; //每添加一个人,通讯录总人数得加1
}
void _display_contact(Pcon pcon)
{
int i=0;
printf("%s\t%s\t%s\t%s\t%s\n","name","sex","age","tele","addr");
for(i=0;i<pcon->size;i++)
{
printf("%s\t%s\t%d\t%s\t%s\n",pcon->data[i].name,
pcon->data[i].sex,pcon->data[i].age,pcon->data[i].tele,pcon->data[i].addr);
}
}
void _del_contact(Pcon pcon)
{
int ret=0;
char name[NAME_MAX]={0};
if(pcon->size==0)
{
printf("当前通讯录为空!\n");
return;
}
else
{
printf("请输入要删除人的姓名:\n");
scanf("%s",name);
ret=find(pcon,name);
if(ret!=-1)
{
pcon->data[ret]=pcon->data[(pcon->size)-1];
pcon->size--; //删除的方法是将数组中最后一个成员移到要删除的成员位置上
printf("删除成功!\n");
}
else
{
printf("未找到要删除的对象!\n");
}
}
}
void _search_contact(Pcon pcon)
{
int ret=0;
char name[NAME_MAX]={0};
printf("请输入要查找的人的姓名:\n");
scanf("%s",name);
ret=find(pcon,name);
if(ret!=-1)
{
printf("%s\t%s\t%d\t%s\t%s\t\n",pcon->data[ret].name,
pcon->data[ret].sex,pcon->data[ret].age,pcon->data[ret].tele,
pcon->data[ret].addr);
}
else
printf("未找到所要查找的人!\n");
}
void _modify_contact(Pcon pcon)
{
int select=0;
int ret=0;
char modify[20]={0};
int year=0;
char name[NAME_MAX]={0};
printf("请输入要修改的人的姓名:\n");
scanf("%s",name);
ret=find(pcon,name);
if(ret!=-1)
{
printf("1.name\n 2.sex\n 3.age\n 4.tele\n 5addr\n");
printf("请输入要修改的项:");
scanf("%d",&select);
switch(select)
{
case 1:
printf("请输入新的名字:");
scanf("%s",modify);
strcpy(pcon->data[ret].name,modify);
printf("修改成功!\n");
break;
case 2:
printf("请输入新的性别:");
scanf("%s",modify);
strcpy(pcon->data[ret].sex,modify);
printf("修改成功!\n");
break;
case 3:
printf("请输入新的电话号:");
scanf("%s",modify);
strcpy(pcon->data[ret].tele,modify);
printf("修改成功!\n");
break;
case 4:
printf("请输入新的地址:");
scanf("%s",modify);
strcpy(pcon->data[ret].addr,modify);
printf("修改成功!\n");
break;
case 5:
printf("请输入新的年龄:");
scanf("%s",year);
pcon->data[ret].age=year;
printf("修改成功!\n");
break;
default:
printf("修改失败!\n");
break;
}
}
else
{
printf("未找到所要修改的人!\n");
}
}
void _sort_contact(Pcon pcon)
{
PerInfo tmp={0};
int i=0;
int j=0;
int flag=0; //表示有序
for(i=0;i<pcon->size-1;i++)
{
flag=0;
for(j=0;j<(pcon->size)-i-1;j++)
{
if(strcmp((pcon->data[j].name),(pcon->data[j+1].name))>0)
tmp=pcon->data[j];
pcon->data[j]=pcon->data[j+1];
pcon->data[j+1]=tmp;
flag=1;
}
if(flag==0)
break;
}
}
void _clear_contact(Pcon pcon)
{
pcon->size=0;
printf("通讯录已清空!\n");
}
void _save_contact(Pcon pcon)
{
int i=0;
FILE *pfWrite=fopen("contact.dat","w"); //FILE一定要大写
if(pfWrite==NULL)
{
perror("open file for write");
exit(EXIT_FAILURE);
}
for(i=0;i<pcon->size;i++)
{
fwrite(&(pcon->data[i]),sizeof(PerInfo),1,pfWrite);
}
fclose(pfWrite);
}
void _load_contact(Pcon pcon)
{
int i=0;
PerInfo tmp={0};
FILE *pfRead=fopen("contact.dat","r");
if(pfRead==NULL)
{
perror("open file for read");
exit(EXIT_FAILURE);
}
while(fread((&tmp),sizeof(PerInfo),1,pfRead))
{
check_capacity(pcon);
pcon->data[i]=tmp;
i++;
pcon->size++;
}
}