当前位置:网站首页>(静态,动态,文件)三个版本的通讯录
(静态,动态,文件)三个版本的通讯录
2022-07-24 05:32:00 【一只大喵咪1201】
作者:一只大喵咪1201
专栏:《C语言学习》
格言:你只管努力,剩下的交给时间!
功能
在这里本喵要使用C语言实现一个通讯录,并且写出它的三个版本,静态版本是最基本的一版,仅能存放有限个联系的人的信息,动态版本是升级板,当容量不够时可以实现扩容,文件版本是最终板,可以将联系人的信息永久的保存下来,不会随着程序的结束而消失。
通信录具有以下功能:
- 增加联系人:ADD
- 删除联系人:DEL
- 查找联系人:SEARCH
- 修改联系人信息:MODIFY
- 显示联系人信息:SHOW
- 将联系人排序:SORT
- 退出通讯录:EXIT
其中,
联系人的信息有:
- 姓名
- 年龄
- 性别
- 电话
- 住址
静态版本
实现思路:
- 创建一个结构体类型用来存放联系人的信息
- 再创建一个结构体类型来存放通讯录的数据,包括联系人组成的数组,和已经存放的联系人个数
需要注意的点在注释中
contact.h中的代码:
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#define MAX_DATA 1000//通讯录可存放最大人数
//将功能用枚举列出
enum Function
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
//创建存放联系人的结构体类型
typedef struct Peo
{
//足够放下任何一个人的信息
char name[20];
int age;
char sex[5];
char tel[12];
char adder[30];
}People;
//创建通讯录的结构体类型
typedef struct Con
{
People data[MAX_DATA];
int count;
}Contact;
//通讯录初始化
void Contact_Init(Contact* pc);
//增加联系人
void ADD_Contact(Contact* pc);
//显示联系人
void SHOW_Init(const Contact* pc);
//删除联系人
void DEL_Contact(Contact* pc);
//查找联系人
void SEARCH_Contact(const Contact* pc);
//修改联系人
void MODIFY_Contact(Contact* pc);
//排序联系人
void SORT_Contact(const Contact* pc);
contact.c中的代码:
#include "contact.h"
//初始化通讯录
void Contact_Init(Contact* pc)
{
assert(pc);//防止是空指针
pc->count = 0;//通讯录人数清0
memset(pc->data, 0, MAX_DATA * sizeof(People));//所有联系人清0
}
//增加联系人
void ADD_Contact(Contact* pc)
{
assert(pc);//防止空指针
printf("请输入联系人姓名:>");
scanf("%s", pc->data[pc->count].name);
printf("请输入联系人年龄:>");
scanf("%d", &(pc->data[pc->count].age));
printf("请输入联系人性别:>");
scanf("%s", pc->data[pc->count].sex);
printf("请输入联系人电话:>");
scanf("%s", pc->data[pc->count].tel);
printf("请输入联系人地址:>");
scanf("%s", pc->data[pc->count].adder);
pc->count++;//联系人个数加1
printf("联系人添加成功\n");
}
//显示联系人
void SHOW_Init(const Contact* pc)//防止内容被修改
{
assert(pc);//防止空指针
int i = 0;
printf("%-20s %-2s %-4s %-11s %-29s\n", "姓名", "年龄", "性别", "电话", "地址");//打印抬头
for (i = 0; i < pc->count; i++)
{
printf("%-20s %-3d %-5s %-12s %-30s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tel,
pc->data[i].adder);
}
}
//仅在这里使用,用static修饰
static int Find_Name(const Contact* pc, const char* ch)
{
assert(pc && ch);//防止空指针
int i = 0;
for (i = 0; i < pc->count; i++)
{
if ((strcmp(ch, pc->data[i].name)) == 0)
{
return i;
}
}
return -1;
}
//删除联系人
void DEL_Contact(Contact* pc)
{
assert(pc);//防止空指针
char ch[20] = {
0 };
printf("请输入要删除的联系人的姓名:>");
scanf("%s", ch);
int ret = Find_Name(pc, ch);
if (ret != -1)
{
//用后面的联系人信息覆盖前面的
int i = ret;
for (i = ret; i < pc->count - 1; i++)
{
People tmp = pc->data[i];
pc->data[i] = pc ->data[i + 1];
pc->data[i + 1] = tmp;
}
pc->count--;//联系人个数减1
}
else
printf("没有联系人\"%s\"\n", ch);
}
//查找联系人
void SEARCH_Contact(const Contact* pc)
{
assert(pc);//防止空指针
char ch[20] = {
0 };
printf("请输入要查找联系人的姓名:>");
scanf("%s", ch);
int ret = Find_Name(pc, ch);
if (ret != -1)
printf("找到联系人\"%s\"\n", ch);
else
printf("没有联系人\"%s\"\n", ch);
}
//修改联系人
static void option()
{
printf("***************************************\n");
printf("****** 1. 年龄 2. 性别 ******\n");
printf("****** 3. 电话 4. 住址 ******\n");
printf("***************************************\n");
}
void MODIFY_Contact(Contact* pc)
{
assert(pc);
char ch[20] = {
0 };
int input = 0;
printf("请输入要修改的联系人姓名:>");
scanf("%s", ch);
int ret = Find_Name(pc, ch);
if (ret != -1)
{
again: option();
printf("请选择要修改的内容:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入新的年龄:>");
scanf("%d", &(pc->data[ret].age));
break;
case 2:
printf("请输入新的性别:>");
scanf("%s", pc->data[ret].sex);
break;
case 3:
printf("请输入新的电话:>");
scanf("%s", pc->data[ret].tel);
break;
case 4:
printf("请输入新的住址:>");
scanf("%s", pc->data[ret].adder);
break;
default:
printf("选择错误,请重新选择\n");
goto again;
}
printf("修改成功\n");
}
else
printf("没有联系人\"%s\"\n", ch);
}
//只在这里使用,用satic修饰
static int cmp_name(const void* e1, const void* e2)
{
assert(e1 && e2);//防止空指针
return strcmp(((People*)e1)->name, ((People*)e2)->name);//相同返回0,小于返回负数,大于返回正数
}
//排序联系人
void SORT_Contact(const Contact* pc)
{
assert(pc);//防止是空指针
qsort(pc->data, pc->count, sizeof(People), cmp_name);
printf("排序成功\n");
}
```c
test.c中的代码:
#include "contact.h"
void menu()
{
printf("*****************************************\n");
printf("****** 1. ADD 2. DEL ******\n");
printf("****** 3. SEARCH 4.MODIFY ******\n");
printf("****** 5. SHOW 6.SORT ******\n");
printf("****** 0. EXIT ******\n");
printf("*****************************************\n");
}
int main()
{
int input = 0;
Contact contact;//创建通讯录变量
Contact_Init(&contact);//初始化通讯录
do
{
menu();//调用菜单
printf("请选择功能:>");
scanf("%d", &input);
//每个功能入口用枚举常量,程序更加清晰
switch (input)
{
case ADD:
ADD_Contact(&contact);//增加联系人
break;
case DEL:
DEL_Contact(&contact);//删除联系人
break;
case SEARCH:
SEARCH_Contact(&contact);//查找联系人
break;
case MODIFY:
MODIFY_Contact(&contact);//修改联系人
break;
case SHOW:
SHOW_Init(&contact);//显示联系人
break;
case SORT:
SORT_Contact(&contact);
break;
case EXIT:
printf("退出通讯录\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
以上便是静态版本的通讯录的代码,效果最后展示。
动态版本
上面静态版本的一个缺点就是,存放联系人的最大人数提前就规定好了,如果人数超出这个限定就无法存进去,如果人数小于这个限定,就会浪费一定的内存空间。所以,动态版本的动态就体现在存放联系人的内存空间的大小是可以随着联系人的多少变化的。
实现思路:
- 通讯录的结构体变量需要创建在堆区上,以便内存空间大小进行调整
- 初始设定通讯录仅可存放三个联系人,当联系人个数达到三个后便扩容,扩容每次增加俩个可以存放联系人的动态内存空间
- 每删除一个联系人,同时减小一个可以存放联系人的动态内存空间
- 在退出通讯录的时候将开辟的动态空间释放
动态版本是在静态版本的基础上修改的,注意看注释
contact.h中的代码:
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
//#define MAX_DATA 1000//通讯录可存放最大人数
#define ORING_NUM 3//初始通讯录容量
#define PER_ADD 2//扩容每次增加人数
//将功能用枚举列出
enum Function
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
//创建存放联系人的结构体类型
typedef struct Peo
{
//足够放下任何一个人的信息
char name[20];
int age;
char sex[5];
char tel[12];
char adder[30];
}People;
//创建通讯录的结构体类型
typedef struct Con
{
//People data[ORING_NUM];
People* data;//要接收动态开辟空间的地址
int count;
int capacity;
}Contact;
//通讯录初始化
void Contact_Init(Contact* pc);
//增加联系人
void ADD_Contact(Contact* pc);
//显示联系人
void SHOW_Init(const Contact* pc);
//删除联系人
void DEL_Contact(Contact* pc);
//查找联系人
void SEARCH_Contact(const Contact* pc);
//修改联系人
void MODIFY_Contact(Contact* pc);
//排序联系人
void SORT_Contact(const Contact* pc);
//摧毁动态空间上的通讯录
void DESTROY_Contact(Contact* pc);
contact.c中的代码:
#include "contact.h"
//初始化通讯录
void Contact_Init(Contact* pc)
{
assert(pc);//防止是空指针
pc->count = 0;//当前通讯录中联系人数初始化为
pc->data = (People*)calloc(ORING_NUM, sizeof(People));//开辟初始个存放联系人的动态内存空间
//判断是否开辟成功
if (pc->data == NULL)
{
perror("calloc");
return;
}
pc->capacity = ORING_NUM;//确定通讯录的初始容量
}
//仅在这里使用扩容功能,用static修饰
static void expand_cap(Contact* pc)
{
assert(pc);//防止空指针
People* str = (People*)realloc(pc->data, (pc->capacity) * sizeof(People) + PER_ADD * sizeof(People));//扩容
//判断是否扩容成功
if (str == NULL)
{
perror("realloc");
return;
}
//保证指针的一致性
if (str != pc->data)
{
pc->data = str;
}
pc->capacity += PER_ADD;//容量改变
printf("扩容成功\n");
}
//增加联系人
void ADD_Contact(Contact* pc)
{
assert(pc);//防止空指针
//联系人个数等于通讯录容量时就扩容
if (pc->count == pc->capacity)
{
expand_cap(pc);//扩容
}
printf("请输入联系人姓名:>");
scanf("%s", pc->data[pc->count].name);
printf("请输入联系人年龄:>");
scanf("%d", &(pc->data[pc->count].age));
printf("请输入联系人性别:>");
scanf("%s", pc->data[pc->count].sex);
printf("请输入联系人电话:>");
scanf("%s", pc->data[pc->count].tel);
printf("请输入联系人地址:>");
scanf("%s", pc->data[pc->count].adder);
pc->count++;//联系人个数加1
printf("联系人添加成功\n");
}
//显示联系人
void SHOW_Init(const Contact* pc)//防止内容被修改
{
assert(pc);//防止空指针
int i = 0;
printf("%-20s %-2s %-4s %-11s %-29s\n", "姓名", "年龄", "性别", "电话", "地址");//打印抬头
for (i = 0; i < pc->count; i++)
{
printf("%-20s %-3d %-5s %-12s %-30s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tel,
pc->data[i].adder);
}
}
//仅在这里使用,用static修饰
static int Find_Name(const Contact* pc, const char* ch)
{
assert(pc && ch);//防止空指针
int i = 0;
for (i = 0; i < pc->count; i++)
{
if ((strcmp(ch, pc->data[i].name)) == 0)
{
return i;
}
}
return -1;
}
//删除联系人
void DEL_Contact(Contact* pc)
{
assert(pc);//防止空指针
char ch[20] = {
0 };
printf("请输入要删除的联系人的姓名:>");
scanf("%s", ch);
int ret = Find_Name(pc, ch);
if (ret != -1)
{
//用后面的联系人信息覆盖前面的
int i = ret;
for (i = ret; i < pc->count - 1; i++)
{
People tmp = pc->data[i];
pc->data[i] = pc ->data[i + 1];
pc->data[i + 1] = tmp;
}
//动态空间减少一个
People* str = realloc(pc->data, (pc->capacity) * sizeof(People) - sizeof(People));
//判断调整是否成功
if (str == NULL)
{
perror("realloc");
return;
}
//保证指针一致
if (str != pc->data)
{
pc->data = str;
}
pc->count--;//联系人个数减1
pc->capacity--;//联系人容量减1
}
else
printf("没有联系人\"%s\"\n", ch);
}
//查找联系人
void SEARCH_Contact(const Contact* pc)
{
assert(pc);//防止空指针
char ch[20] = {
0 };
printf("请输入要查找联系人的姓名:>");
scanf("%s", ch);
int ret = Find_Name(pc, ch);
if (ret != -1)
printf("找到联系人\"%s\"\n", ch);
else
printf("没有联系人\"%s\"\n", ch);
}
//修改联系人
static void option()
{
printf("***************************************\n");
printf("****** 1. 年龄 2. 性别 ******\n");
printf("****** 3. 电话 4. 住址 ******\n");
printf("***************************************\n");
}
void MODIFY_Contact(Contact* pc)
{
assert(pc);
char ch[20] = {
0 };
int input = 0;
printf("请输入要修改的联系人姓名:>");
scanf("%s", ch);
int ret = Find_Name(pc, ch);
if (ret != -1)
{
again: option();
printf("请选择要修改的内容:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入新的年龄:>");
scanf("%d", &(pc->data[ret].age));
break;
case 2:
printf("请输入新的性别:>");
scanf("%s", pc->data[ret].sex);
break;
case 3:
printf("请输入新的电话:>");
scanf("%s", pc->data[ret].tel);
break;
case 4:
printf("请输入新的住址:>");
scanf("%s", pc->data[ret].adder);
break;
default:
printf("选择错误,请重新选择\n");
goto again;
}
printf("修改成功\n");
}
else
printf("没有联系人\"%s\"\n", ch);
}
//只在这里使用,用satic修饰
static int cmp_name(const void* e1, const void* e2)
{
assert(e1 && e2);//防止空指针
return strcmp(((People*)e1)->name, ((People*)e2)->name);//相同返回0,小于返回负数,大于返回正数
}
//排序联系人
void SORT_Contact(const Contact* pc)
{
assert(pc);//防止是空指针
qsort(pc->data, pc->count, sizeof(People), cmp_name);
printf("排序成功\n");
}
//摧毁动态空间上的通讯录
void DESTROY_Contact(Contact* pc)
{
assert(pc);//防止空指针
free(pc->data);
pc->data = NULL;
}
test.c中的代码:
#include "contact.h"
void menu()
{
printf("*****************************************\n");
printf("****** 1. ADD 2. DEL ******\n");
printf("****** 3. SEARCH 4.MODIFY ******\n");
printf("****** 5. SHOW 6.SORT ******\n");
printf("****** 0. EXIT ******\n");
printf("*****************************************\n");
}
int main()
{
int input = 0;
Contact contact;//创建通讯录变量
Contact_Init(&contact);//初始化通讯录
do
{
menu();//调用菜单
printf("请选择功能:>");
scanf("%d", &input);
//每个功能入口用枚举常量,程序更加清晰
switch (input)
{
case ADD:
ADD_Contact(&contact);//增加联系人
break;
case DEL:
DEL_Contact(&contact);//删除联系人
break;
case SEARCH:
SEARCH_Contact(&contact);//查找联系人
break;
case MODIFY:
MODIFY_Contact(&contact);//修改联系人
break;
case SHOW:
SHOW_Init(&contact);//显示联系人
break;
case SORT:
SORT_Contact(&contact);
break;
case EXIT:
DESTROY_Contact(&contact);//摧毁动态空间上的通讯录
printf("退出通讯录\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
仔细看代码就会发现,仅在初始化以及增加删除联系人的函数中使用了动态内存空间的操作,其他和静态版本是一样的。
文件版本
无论是静态版本还是动态版本,它们都有一个致命的缺陷,就是在程序执行结束以后,联系人的信息就消失了,每执行一次程序就得重新存一下联系人,这样的使用无疑是非常不好的,为了能够让联系人的信息一直存在,我们可以把它们的信息放在文件中,存放在硬盘上,这样就不会消失了。
实现思路:
- 在动态版本的基础上,在程序结束的时候,要将所有联系人的信息保存到文件中
- 在程序开始执行时,初始化的过程中需要将文件中联系人的信息读出来
仅在动态版本的基础上做了修改,注意看注释
contact.h中的代码:
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
//#define MAX_DATA 1000//通讯录可存放最大人数
#define ORING_NUM 3//初始通讯录容量
#define PER_ADD 2//扩容每次增加人数
//将功能用枚举列出
enum Function
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
//创建存放联系人的结构体类型
typedef struct Peo
{
//足够放下任何一个人的信息
char name[20];
int age;
char sex[10];
char tel[12];
char adder[30];
}People;
//创建通讯录的结构体类型
typedef struct Con
{
//People data[ORING_NUM];
People* data;//要接收动态开辟空间的地址
int count;
int capacity;
}Contact;
//通讯录初始化
void Contact_Init(Contact* pc);
//增加联系人
void ADD_Contact(Contact* pc);
//显示联系人
void SHOW_Init(const Contact* pc);
//删除联系人
void DEL_Contact(Contact* pc);
//查找联系人
void SEARCH_Contact(const Contact* pc);
//修改联系人
void MODIFY_Contact(Contact* pc);
//排序联系人
void SORT_Contact(const Contact* pc);
//摧毁动态空间上的通讯录
void DESTROY_Contact(Contact* pc);
//将联系人信息保存到文件中
void SAVE_Contact(const Contact* pc);
contact.c中的代码:
#include "contact.h"
//仅在这里使用扩容功能,用static修饰
static void expand_cap(Contact* pc)
{
assert(pc);//防止空指针
People* str = (People*)realloc(pc->data, (pc->capacity) * sizeof(People) + PER_ADD * sizeof(People));//扩容
//判断是否扩容成功
if (str == NULL)
{
perror("realloc");
return;
}
//保证指针的一致性
if (str != pc->data)
{
pc->data = str;
}
pc->capacity += PER_ADD;//容量改变
//printf("扩容成功\n");
}
//加载通讯录,仅在这里使用
static void LOAD_Contact(Contact* pc)
{
assert(pc);//防止是空指针
FILE* pf = fopen("contact.txt", "rb");//以二进制读的方式打开contact.txt文件
//判断文件是否成功打开
if (pf == NULL)
{
perror("fopen");
return;
}
//读取联系人信息
while (fread(&(pc->data[pc->count]), sizeof(People), 1, pf) == 1)
{
pc->count++;//联系人数量增加
//判断是否需要扩容
if (pc->count == pc->capacity)
{
expand_cap(pc);
}
}
//关闭文件
fclose(pf);
pf = NULL;
}
//初始化通讯录
void Contact_Init(Contact* pc)
{
assert(pc);//防止是空指针
pc->count = 0;//当前通讯录中联系人数初始化为
pc->data = (People*)calloc(ORING_NUM, sizeof(People));//开辟初始个存放联系人的动态内存空间
//判断是否开辟成功
if (pc->data == NULL)
{
perror("calloc");
return;
}
pc->capacity = ORING_NUM;//确定通讯录的初始容量
LOAD_Contact(pc);//加载通讯录
}
//增加联系人
void ADD_Contact(Contact* pc)
{
assert(pc);//防止空指针
//联系人个数等于通讯录容量时就扩容
if (pc->count == pc->capacity)
{
expand_cap(pc);//扩容
}
printf("请输入联系人姓名:>");
scanf("%s", pc->data[pc->count].name);
printf("请输入联系人年龄:>");
scanf("%d", &(pc->data[pc->count].age));
printf("请输入联系人性别:>");
scanf("%s", pc->data[pc->count].sex);
printf("请输入联系人电话:>");
scanf("%s", pc->data[pc->count].tel);
printf("请输入联系人地址:>");
scanf("%s", pc->data[pc->count].adder);
pc->count++;//联系人个数加1
printf("联系人添加成功\n");
}
//显示联系人
void SHOW_Init(const Contact* pc)//防止内容被修改
{
assert(pc);//防止空指针
int i = 0;
printf("%-20s\t%-3s\t%-10s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址");//打印抬头
for (i = 0; i < pc->count; i++)
{
printf("%-20s\t%-3d\t%-10s\t%-12s\t%-30s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tel,
pc->data[i].adder);
}
}
//仅在这里使用,用static修饰
static int Find_Name(const Contact* pc, const char* ch)
{
assert(pc && ch);//防止空指针
int i = 0;
for (i = 0; i < pc->count; i++)
{
if ((strcmp(ch, pc->data[i].name)) == 0)
{
return i;
}
}
return -1;
}
//删除联系人
void DEL_Contact(Contact* pc)
{
assert(pc);//防止空指针
char ch[20] = {
0 };
printf("请输入要删除的联系人的姓名:>");
scanf("%s", ch);
int ret = Find_Name(pc, ch);
if (ret != -1)
{
//用后面的联系人信息覆盖前面的
int i = ret;
for (i = ret; i < pc->count - 1; i++)
{
People tmp = pc->data[i];
pc->data[i] = pc ->data[i + 1];
pc->data[i + 1] = tmp;
}
//动态空间减少一个
People* str = realloc(pc->data, (pc->capacity) * sizeof(People) - sizeof(People));
//判断调整是否成功
if (str == NULL)
{
perror("realloc");
return;
}
//保证指针一致
if (str != pc->data)
{
pc->data = str;
}
pc->count--;//联系人个数减1
pc->capacity--;//联系人容量减1
}
else
printf("没有联系人\"%s\"\n", ch);
}
//查找联系人
void SEARCH_Contact(const Contact* pc)
{
assert(pc);//防止空指针
char ch[20] = {
0 };
printf("请输入要查找联系人的姓名:>");
scanf("%s", ch);
int ret = Find_Name(pc, ch);
if (ret != -1)
printf("找到联系人\"%s\"\n", ch);
else
printf("没有联系人\"%s\"\n", ch);
}
//修改联系人
static void option()
{
printf("***************************************\n");
printf("****** 1. 年龄 2. 性别 ******\n");
printf("****** 3. 电话 4. 住址 ******\n");
printf("***************************************\n");
}
void MODIFY_Contact(Contact* pc)
{
assert(pc);
char ch[20] = {
0 };
int input = 0;
printf("请输入要修改的联系人姓名:>");
scanf("%s", ch);
int ret = Find_Name(pc, ch);
if (ret != -1)
{
again: option();
printf("请选择要修改的内容:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入新的年龄:>");
scanf("%d", &(pc->data[ret].age));
break;
case 2:
printf("请输入新的性别:>");
scanf("%s", pc->data[ret].sex);
break;
case 3:
printf("请输入新的电话:>");
scanf("%s", pc->data[ret].tel);
break;
case 4:
printf("请输入新的住址:>");
scanf("%s", pc->data[ret].adder);
break;
default:
printf("选择错误,请重新选择\n");
goto again;
}
printf("修改成功\n");
}
else
printf("没有联系人\"%s\"\n", ch);
}
//只在这里使用,用satic修饰
static int cmp_name(const void* e1, const void* e2)
{
assert(e1 && e2);//防止空指针
return strcmp(((People*)e1)->name, ((People*)e2)->name);//相同返回0,小于返回负数,大于返回正数
}
//排序联系人
void SORT_Contact(const Contact* pc)
{
assert(pc);//防止是空指针
qsort(pc->data, pc->count, sizeof(People), cmp_name);
printf("排序成功\n");
}
//摧毁动态空间上的通讯录
void DESTROY_Contact(Contact* pc)
{
assert(pc);//防止空指针
free(pc->data);
pc->data = NULL;
}
//将联系人信息保存到文件中
void SAVE_Contact(const Contact* pc)
{
assert(pc);//防止空指针
FILE* pf = fopen("contact.txt", "wb");//以二进制写的形式打开contact.txt文件
//判断是否打开成功
if (pf == NULL)
{
perror("fopen");
return;
}
//保存信息
fwrite(pc->data, sizeof(People), pc->count, pf);//将联系人信息输出到文件中
//关闭文件
fclose(pf);
pf = NULL;
}
test.c中的代码:
#include "contact.h"
void menu()
{
printf("*****************************************\n");
printf("****** 1. ADD 2. DEL ******\n");
printf("****** 3. SEARCH 4.MODIFY ******\n");
printf("****** 5. SHOW 6.SORT ******\n");
printf("****** 0. EXIT ******\n");
printf("*****************************************\n");
}
int main()
{
int input = 0;
Contact contact;//创建通讯录变量
Contact_Init(&contact);//初始化通讯录
do
{
menu();//调用菜单
printf("请选择功能:>");
scanf("%d", &input);
//每个功能入口用枚举常量,程序更加清晰
switch (input)
{
case ADD:
ADD_Contact(&contact);//增加联系人
break;
case DEL:
DEL_Contact(&contact);//删除联系人
break;
case SEARCH:
SEARCH_Contact(&contact);//查找联系人
break;
case MODIFY:
MODIFY_Contact(&contact);//修改联系人
break;
case SHOW:
SHOW_Init(&contact);//显示联系人
break;
case SORT:
SORT_Contact(&contact);
break;
case EXIT:
SAVE_Contact(&contact);//将联系人信息保存到文件中
DESTROY_Contact(&contact);//摧毁动态空间上的通讯录
printf("退出通讯录\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
效果展示

这便是通讯录最终版本的效果展示。
总结
本喵通过三个版本的通讯录给大家演示了怎么样一步一步完善自己的程序,这个过程其实也是我们日常工作学习中不断经历的过程,希望这篇文章对各位有所帮助。
边栏推荐
- 系统安全及应用
- [small object velocimeter] only principle, no code
- Flex layout
- Explain the event cycle mechanism and differences between browser and node in detail
- MySQL batch modifies the data table code and character set to utf8mb4
- SSH远程访问及控制
- These 10 kinds of timed tasks have been learned, and you can float directly
- Log collection and analysis platform
- Special effects - return to the top (kitten effects)
- Disk management and file system
猜你喜欢
随机推荐
Backup MySQL database with bat script under Windows
Directory and file management
Customize ZABBIX agent RPM package
grep与正则的搭配使用
Promise (try to implement a promise by yourself) more detailed comments and other interfaces are not completed yet. Let's continue next time.
【LVGL(4)】对象的事件及事件冒泡
I have seven schemes to realize web real-time message push, seven!
Iterators and generators
SSH Remote Access and control
Browser local storage
利用sshpass批量实现基于key验证
kubernetes简介和架构及其原理
【LVGL(3)】设置对象大小、位置、盒子模型、状态
SSH远程访问及控制
【微信小程序】一文搞懂条件渲染、列表渲染以及wxss模板样式
Go environment construction and start
DHCP原理与配置
Special effects - when the mouse moves, there will be a custom expression trail
File system and log analysis
Today, let's talk about the underlying architecture design of MySQL database. How much do you know?










