一、简单通讯录实现
1. 通讯录菜单
实现与用户交互。
void eum()
{
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");
}
效果图:
2. 枚举法定义结构体
在主函数中用这些定义出来的代替whitch语句中case 0~6的值。
enum OPIION
{
EXIT,//0
ADD,//1
DEL,//2
SEARCH,//3
MODIFY,//4
SHOW,//5
SORT//6
};
3. 定义联系人和通讯录
实现通讯录,必须要有联系人的其它成员,以及通讯录本身
3.1 定义联系人
//联系人类型的声明
typedef struct PeoInfo
{
char name[MAX_name];
int age;
char sex[MAX_sex];
char tele[MAX_tele];
char addr[MAX_addr];
}PeoInfo;
3.2 定义通讯录
//通讯录
typedef struct Contact
{
PeoInfo data[MAX];//存放100个
int sz;//存放已有的个数
}Contact;
4. 定义全局变量
这样子方便修改
#define MAX 100
#define MAX_name 20
#define MAX_sex 5
#define MAX_tele 12
#define MAX_addr 30
5. 初始化通讯录
初始化全为0,而不是随机值
void InitContact(Contact* pc)
{
assert(pc);
memset(pc->data, 0, sizeof(pc->data));
pc->sz = 0;
}
6. 找到要删除的人
简单实现
int del = 0;
int flage = 0;
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
del = i;
flage = 1;
break;
}
}
if (flage == 0)
{
printf("要删除的人不存在\n");
return;
}
7. 用函数封装找要删除的人
改进
//函数封装找要删除的人
static int FindByName(const Contact* pc, char name[])
{
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;//找到了
}
}
return -1;//找不到
}
8. 通讯录功能实现
8.1 增加联系人
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == MAX)
{
printf("通讯录已满,无法添加\n");
return;
}
printf("请输入名字:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("成功增加联系人\n");
}
效果图:
8.2 删除联系人
void DelContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[MAX_name] = { 0 };
assert(pc);
//删除
printf("请输入要删除的名字:>");
scanf("%s", name);
//找到要删除的人
/*int del = 0;
int flage = 0;
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
del = i;
flage = 1;
break;
}
}
if (flage == 0)
{
printf("要删除的人不存在\n");
return;
}*/
//找到要删除的人
int del = FindByName(pc, name);
if (del == -1)
{
printf("要删除的人不存在\n");
return;
}
//删除坐标为del的联系人
for (int i = del; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
效果图:
8.3 查找联系人
void SearchContact(const Contact* pc)
{
assert(pc);
char name[MAX_name] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
//打印列标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
}
}
效果图:
8.4 修改联系人
void ModifyContact(Contact* pc)
{
assert(pc);
char name[MAX_name] = { 0 };
printf("请输入要修改人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->data[pos].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pos].age));
printf("请输入性别:>");
scanf("%s", pc->data[pos].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pos].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
}
效果图:
8.5 显示联系人
void ShowContact(const Contact* pc)
{
//打印列标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
for (int i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
8.6 排序联系人
void SortContact(Contact* pc)
{
if (pc->sz <= 0)
{
printf("通讯录中没有联系人,请添加!\n");
}
for (int i = 0; i < pc->sz - 1; i++)
{
for (int j = 0; j < pc->sz - i - 1; j++)
{
if ((pc->data[j].age - pc->data[j + 1].age) > 0)
{
PeoInfo tmp = pc->data[j];
pc->data[j] = pc->data[j + 1];
pc->data[j + 1] = tmp;
}
}
}
printf("排序成功\n");
}
排序前:
排序后:
9. test.c主文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void eum()
{
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");
}
void test()
{
int input = 0;
//首先得有通讯录
Contact con;
InitContact(&con);
do
{
eum();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
//增加
AddContact(&con);
break;
case DEL:
//删除
DelContact(&con);
break;
case SEARCH:
//查找
SearchContact(&con);
break;
case MODIFY:
//修改
ModifyContact(&con);
break;
case SHOW:
//显示
ShowContact(&con);
break;
case SORT:
//排序
SortContact(&con);
break;
case EXIT:
printf("退出通讯录\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
10. contact.c函数实现文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void InitContact(Contact* pc)
{
assert(pc);
memset(pc->data, 0, sizeof(pc->data));
pc->sz = 0;
}
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == MAX)
{
printf("通讯录已满,无法添加\n");
return;
}
printf("请输入名字:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("成功增加联系人\n");
}
void ShowContact(const Contact* pc)
{
//打印列标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
for (int i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
//函数封装找要删除的人
static int FindByName(const Contact* pc, char name[])
{
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;//找到了
}
}
return -1;//找不到
}
void DelContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[MAX_name] = { 0 };
assert(pc);
//删除
printf("请输入要删除的名字:>");
scanf("%s", name);
//找到要删除的人
/*int del = 0;
int flage = 0;
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
del = i;
flage = 1;
break;
}
}
if (flage == 0)
{
printf("要删除的人不存在\n");
return;
}*/
//找到要删除的人
int del = FindByName(pc, name);
if (del == -1)
{
printf("要删除的人不存在\n");
return;
}
//删除坐标为del的联系人
for (int i = del; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
void SearchContact(const Contact* pc)
{
assert(pc);
char name[MAX_name] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
//打印列标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
}
}
void ModifyContact(Contact* pc)
{
assert(pc);
char name[MAX_name] = { 0 };
printf("请输入要修改人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->data[pos].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pos].age));
printf("请输入性别:>");
scanf("%s", pc->data[pos].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pos].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
}
void SortContact(Contact* pc)
{
if (pc->sz <= 0)
{
printf("通讯录中没有联系人,请添加!\n");
}
for (int i = 0; i < pc->sz - 1; i++)
{
for (int j = 0; j < pc->sz - i - 1; j++)
{
if ((pc->data[j].age - pc->data[j + 1].age) > 0)
{
PeoInfo tmp = pc->data[j];
pc->data[j] = pc->data[j + 1];
pc->data[j + 1] = tmp;
}
}
}
printf("排序成功\n");
}
11. contact.h函数声明文件
#pragma once
#include <string.h>
#include <assert.h>
#include <stdio.h>
#define MAX 100
#define MAX_name 20
#define MAX_sex 5
#define MAX_tele 12
#define MAX_addr 30
enum OPIION
{
EXIT,//0
ADD,//1
DEL,//2
SEARCH,//3
MODIFY,//4
SHOW,//5
SORT//6
};
//联系人类型的声明
typedef struct PeoInfo
{
char name[MAX_name];
int age;
char sex[MAX_sex];
char tele[MAX_tele];
char addr[MAX_addr];
}PeoInfo;
//通讯录
typedef struct Contact
{
PeoInfo data[MAX];//存放100个
int sz;//存放已有的个数
}Contact;
//函数声明
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//显示所有联系人的信息
void ShowContact(const Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(const Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
//按年龄排序联系人
void SortContact(Contact* pc);
二、动态内存实现
1. 改造目标
- 通讯录的空间不是固定的,大小是可以调整的。
- 默认能放3个人的信息,如果不够,就每次增加2个人的信息
2. 动态版本初始化
//动态版本
void InitContact(Contact* pc)
{
assert(pc);
pc->data = (PeoInfo*)malloc(DEFAULT_sz * sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("InitContact");//显示错误信息
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_sz;
}
3. 全局变量声明
#define DEFAULT_sz 3
#define INC_sz 2
4. 动态版本通讯录
typedef struct Contact
{
PeoInfo* data;//指向了存放数据的空间
int sz;//记录的当前放的有效有效元素的个数
int capacity;//通讯录当前的最大容量
}Contact;
5.增容函数
//增容函数实现
int CheckCapacity(Contact* pc)
{
if (pc->sz == pc->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_sz) * sizeof(PeoInfo));
if (ptr == NULL)
{
perror("CheckCapacity");
return 0;//增容失败
}
else
{
pc->data = ptr;
pc->capacity += INC_sz;
printf("增容成功\n");
return 1;//增容成功
}
}
return 1;
}
6. 动态版本增加函数
//动态版本
void AddContact(Contact* pc)
{
assert(pc);
//判断增容是否成功
if (0 == CheckCapacity(pc))
{
return;
}
printf("请输入名字:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("成功增加联系人\n");
}
效果图:
7. 销毁通讯录
void DestoryContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
8. test.c主文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void eum()
{
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");
}
void test()
{
int input = 0;
//首先得有通讯录
Contact con;
InitContact(&con);
do
{
eum();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
//增加
AddContact(&con);
break;
case DEL:
//删除
DelContact(&con);
break;
case SEARCH:
//查找
SearchContact(&con);
break;
case MODIFY:
//修改
ModifyContact(&con);
break;
case SHOW:
//显示
ShowContact(&con);
break;
case SORT:
//排序
SortContact(&con);
break;
case EXIT:
//释放通讯录
DestoryContact(&con);
printf("退出通讯录\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
9. contact.c函数实现文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
//静态版本
//void InitContact(Contact* pc)
//{
// assert(pc);
// memset(pc->data, 0, sizeof(pc->data));
// pc->sz = 0;
//}
//动态版本
void InitContact(Contact* pc)
{
assert(pc);
pc->data = (PeoInfo*)malloc(DEFAULT_sz * sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("InitContact");//显示错误信息
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_sz;
}
//静态版本
//void AddContact(Contact* pc)
//{
// assert(pc);
// if (pc->sz == MAX)
// {
// printf("通讯录已满,无法添加\n");
// return;
// }
// printf("请输入名字:>");
// scanf("%s", pc->data[pc->sz].name);
// printf("请输入年龄:>");
// scanf("%d", &(pc->data[pc->sz].age));
// printf("请输入性别:>");
// scanf("%s", pc->data[pc->sz].sex);
// printf("请输入电话:>");
// scanf("%s", pc->data[pc->sz].tele);
// printf("请输入地址:>");
// scanf("%s", pc->data[pc->sz].addr);
//
//
// pc->sz++;
// printf("成功增加联系人\n");
//}
//增容函数实现
int CheckCapacity(Contact* pc)
{
if (pc->sz == pc->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_sz) * sizeof(PeoInfo));
if (ptr == NULL)
{
perror("CheckCapacity");
return 0;//增容失败
}
else
{
pc->data = ptr;
pc->capacity += INC_sz;
printf("增容成功\n");
return 1;//增容成功
}
}
return 1;
}
//动态版本
void AddContact(Contact* pc)
{
assert(pc);
//判断增容是否成功
if (0 == CheckCapacity(pc))
{
return;
}
printf("请输入名字:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("成功增加联系人\n");
}
void ShowContact(const Contact* pc)
{
//打印列标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
for (int i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
//函数封装找要删除的人
static int FindByName(const Contact* pc, char name[])
{
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;//找到了
}
}
return -1;//找不到
}
void DelContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[MAX_name] = { 0 };
assert(pc);
//删除
printf("请输入要删除的名字:>");
scanf("%s", name);
//找到要删除的人
/*int del = 0;
int flage = 0;
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
del = i;
flage = 1;
break;
}
}
if (flage == 0)
{
printf("要删除的人不存在\n");
return;
}*/
//找到要删除的人
int del = FindByName(pc, name);
if (del == -1)
{
printf("要删除的人不存在\n");
return;
}
//删除坐标为del的联系人
for (int i = del; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
void SearchContact(const Contact* pc)
{
assert(pc);
char name[MAX_name] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
//打印列标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
}
}
void ModifyContact(Contact* pc)
{
assert(pc);
char name[MAX_name] = { 0 };
printf("请输入要修改人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->data[pos].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pos].age));
printf("请输入性别:>");
scanf("%s", pc->data[pos].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pos].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
}
void SortContact(Contact* pc)
{
if (pc->sz <= 0)
{
printf("通讯录中没有联系人,请添加!\n");
}
for (int i = 0; i < pc->sz - 1; i++)
{
for (int j = 0; j < pc->sz - i - 1; j++)
{
if ((pc->data[j].age - pc->data[j + 1].age) > 0)
{
PeoInfo tmp = pc->data[j];
pc->data[j] = pc->data[j + 1];
pc->data[j + 1] = tmp;
}
}
}
printf("排序成功\n");
}
void DestoryContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
10. contact.h函数声明文件
#pragma once
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
#define MAX_name 20
#define MAX_sex 5
#define MAX_tele 12
#define MAX_addr 30
#define DEFAULT_sz 3
#define INC_sz 2
enum OPIION
{
EXIT,//0
ADD,//1
DEL,//2
SEARCH,//3
MODIFY,//4
SHOW,//5
SORT//6
};
//联系人类型的声明
typedef struct PeoInfo
{
char name[MAX_name];
int age;
char sex[MAX_sex];
char tele[MAX_tele];
char addr[MAX_addr];
}PeoInfo;
//通讯录
//静态版本
//typedef struct Contact
//{
// PeoInfo data[MAX];//存放100个
// int sz;//存放已有的个数
//}Contact;
//动态版本
typedef struct Contact
{
PeoInfo* data;//指向了存放数据的空间
int sz;//记录的当前放的有效有效元素的个数
int capacity;//通讯录当前的最大容量
}Contact;
//函数声明
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//显示所有联系人的信息
void ShowContact(const Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(const Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
//按年龄排序联系人
void SortContact(Contact* pc);
//销毁通讯录
void DestoryContact(Contact* pc);
三、通讯录的信息保存在文件里
1. 保存通讯录信息到文件
void SaveContact(Contact* pc)
{
FILE* pf = fopen("contact.dat", "wb");
if (pf == NULL)
{
perror("SaveContact");
return;
}
//写数据
for (int i = 0; i < pc->sz; i++)
{
//写文件
fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
1.1 修改的内容
先添加4个联系人到通讯录中,再通过文件保存着4个联系人的信息。
运行程序后退出通讯录
打开文件夹,找到contact.dat文件,并以记事本的形式打开。
打开之后就是这样,为什么会这样,因为我们是以二进制的方式存储进去的,所以我们看不懂。
2. 读信息
//读信息
void LoadContact(Contact* pc)
{
//打开文件
FILE* pf = fopen("contact.dat", "rb");
if (pf == NULL)
{
perror("LoadContact");
return;
}
//读文件
PeoInfo tmp = { 0 };
while (fread(&tmp, sizeof(PeoInfo), 1, pf))
{
//先检查容量
if (0 == CheckCapacity(pc))
return;
//保存
pc->data[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
再运行一次:
为什么会显示增容成功,因为刚开始存入了4个联系人信息已经超过了本来的默认最大容量3,所以一上来就打印增容成功。
再增加几个联系人运行后退出通讯录
再重新运行:
这样子就增容了2次。
3. test.c主文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void eum()
{
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");
}
void test()
{
int input = 0;
//首先得有通讯录
Contact con;
InitContact(&con);
do
{
eum();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
//增加
AddContact(&con);
break;
case DEL:
//删除
DelContact(&con);
break;
case SEARCH:
//查找
SearchContact(&con);
break;
case MODIFY:
//修改
ModifyContact(&con);
break;
case SHOW:
//显示
ShowContact(&con);
break;
case SORT:
//排序
SortContact(&con);
break;
case EXIT:
//信息保存到文件中
SaveContact(&con);
//释放通讯录
DestoryContact(&con);
printf("退出通讯录\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
4. contact.c函数实现文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
//静态版本
//void InitContact(Contact* pc)
//{
// assert(pc);
// memset(pc->data, 0, sizeof(pc->data));
// pc->sz = 0;
//}
//容量函数声明
int CheckCapacity(Contact* pc);
//读信息
void LoadContact(Contact* pc)
{
//打开文件
FILE* pf = fopen("contact.dat", "rb");
if (pf == NULL)
{
perror("LoadContact");
return;
}
//读文件
PeoInfo tmp = { 0 };
while (fread(&tmp, sizeof(PeoInfo), 1, pf))
{
//先检查容量
if (0 == CheckCapacity(pc))
return;
//保存
pc->data[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
//动态版本
void InitContact(Contact* pc)
{
assert(pc);
pc->data = (PeoInfo*)malloc(DEFAULT_sz * sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("InitContact");//显示错误信息
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_sz;
//文件中保存的信息加载到通讯录中
LoadContact(pc);
}
//静态版本
//void AddContact(Contact* pc)
//{
// assert(pc);
// if (pc->sz == MAX)
// {
// printf("通讯录已满,无法添加\n");
// return;
// }
// printf("请输入名字:>");
// scanf("%s", pc->data[pc->sz].name);
// printf("请输入年龄:>");
// scanf("%d", &(pc->data[pc->sz].age));
// printf("请输入性别:>");
// scanf("%s", pc->data[pc->sz].sex);
// printf("请输入电话:>");
// scanf("%s", pc->data[pc->sz].tele);
// printf("请输入地址:>");
// scanf("%s", pc->data[pc->sz].addr);
//
//
// pc->sz++;
// printf("成功增加联系人\n");
//}
//增容函数实现
int CheckCapacity(Contact* pc)
{
if (pc->sz == pc->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_sz) * sizeof(PeoInfo));
if (ptr == NULL)
{
perror("CheckCapacity");
return 0;//增容失败
}
else
{
pc->data = ptr;
pc->capacity += INC_sz;
printf("增容成功\n");
return 1;//增容成功
}
}
return 1;
}
//动态版本
void AddContact(Contact* pc)
{
assert(pc);
//判断增容是否成功
if (0 == CheckCapacity(pc))
{
return;
}
printf("请输入名字:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("成功增加联系人\n");
}
void ShowContact(const Contact* pc)
{
//打印列标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
for (int i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
//函数封装找要删除的人
static int FindByName(const Contact* pc, char name[])
{
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;//找到了
}
}
return -1;//找不到
}
void DelContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[MAX_name] = { 0 };
assert(pc);
//删除
printf("请输入要删除的名字:>");
scanf("%s", name);
//找到要删除的人
/*int del = 0;
int flage = 0;
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
del = i;
flage = 1;
break;
}
}
if (flage == 0)
{
printf("要删除的人不存在\n");
return;
}*/
//找到要删除的人
int del = FindByName(pc, name);
if (del == -1)
{
printf("要删除的人不存在\n");
return;
}
//删除坐标为del的联系人
for (int i = del; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
void SearchContact(const Contact* pc)
{
assert(pc);
char name[MAX_name] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
//打印列标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
}
}
void ModifyContact(Contact* pc)
{
assert(pc);
char name[MAX_name] = { 0 };
printf("请输入要修改人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->data[pos].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pos].age));
printf("请输入性别:>");
scanf("%s", pc->data[pos].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pos].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
}
void SortContact(Contact* pc)
{
if (pc->sz <= 0)
{
printf("通讯录中没有联系人,请添加!\n");
}
for (int i = 0; i < pc->sz - 1; i++)
{
for (int j = 0; j < pc->sz - i - 1; j++)
{
if ((pc->data[j].age - pc->data[j + 1].age) > 0)
{
PeoInfo tmp = pc->data[j];
pc->data[j] = pc->data[j + 1];
pc->data[j + 1] = tmp;
}
}
}
printf("排序成功\n");
}
void DestoryContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
void SaveContact(Contact* pc)
{
FILE* pf = fopen("contact.dat", "wb");
if (pf == NULL)
{
perror("SaveContact");
return;
}
//写数据
for (int i = 0; i < pc->sz; i++)
{
//写文件
fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
5. contact.h函数声明文件
#pragma once
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
#define MAX_name 20
#define MAX_sex 5
#define MAX_tele 12
#define MAX_addr 30
#define DEFAULT_sz 3
#define INC_sz 2
enum OPIION
{
EXIT,//0
ADD,//1
DEL,//2
SEARCH,//3
MODIFY,//4
SHOW,//5
SORT//6
};
//联系人类型的声明
typedef struct PeoInfo
{
char name[MAX_name];
int age;
char sex[MAX_sex];
char tele[MAX_tele];
char addr[MAX_addr];
}PeoInfo;
//通讯录
//静态版本
//typedef struct Contact
//{
// PeoInfo data[MAX];//存放100个
// int sz;//存放已有的个数
//}Contact;
//动态版本
typedef struct Contact
{
PeoInfo* data;//指向了存放数据的空间
int sz;//记录的当前放的有效有效元素的个数
int capacity;//通讯录当前的最大容量
}Contact;
//函数声明
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//显示所有联系人的信息
void ShowContact(const Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(const Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
//按年龄排序联系人
void SortContact(Contact* pc);
//销毁通讯录
void DestoryContact(Contact* pc);
//保存通讯录信息到文件
void SaveContact(Contact* pc);