test.c 测试通讯录逻辑的模块
contact.h 头文件的包含,类型定义,函数声明
contact. c 通讯录相关函数的实现
版本1 - 静态版本
静态版本,顾名思义,就是能储存的联系人的数量是静态的,固定的,比如通讯录的大小为1000,那么就只能储存1000位联系人的信息,不能多存。
思路:
memset函数 http://t.csdn.cn/zZTHJ
完整代码:
排序功能使用qsort函数,此篇文章不再实现。
test.c
#include"contact.h"
//通讯录
//1.通讯录中能够存放1000个人的信息
// 每个人的信息:
// 名字+年龄+性别+电话+地址
// 2.增加人的信息
// 3.删除指定人的信息
// 4.查找指定人的信息
// 5.修改指定人的信息
// 6.排序通讯录的信息
void meau()
{
printf("****************************************\n");
printf("*********** 1.add 2.del ***********\n");
printf("*********** 3.serrch 4.modify ********\n");
printf("*********** 5.sort 6.print ********\n");
printf("************** 0.exit ****************\n");
printf("****************************************\n");
}
enum Option
{
EXIT,//0
ADD,//1
DEL,//2
SEARCH,//3
MODIFY,//4
SORT,//5
PRINT//6
};
int main()
{
int input = 0;//创建通讯录
struct Contact con;//通讯录
//初始化通讯录
InitContact(&con);
do
{
meau();
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 SORT:
break;
case PRINT:
PrintContact(&con);
break;
case EXIT:
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
contact.h
#pragma once
#include <stdio.h>
#include<string.h>
//类型的定义
#define MAXE_NAME 20
#define MAX_SEX 10
#define MAX_DELE 12
#define MAX_ADDREES 30
#define MAX 1000
struct PeoInfo
{
char name[MAXE_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_DELE];
char address[MAX_ADDREES];
}PeoInfo;
//通讯录
struct Contact
{
struct PeoInfo data[MAX];//存放添加进来的人的信息
int sz;//记录的是当前通讯录中已有元素的个数
};
//初始化通讯录
void InitContact(struct Contact* pc);
//增加联系人
void AddContact(struct Contact* pc);
//打印联系人信息
void PrintContact(const struct Contact* pc);//只打印,不修改,加上const,可以防止不小心修改,更安全
//查找某个人是否存在
int FindByname(struct Contact* pc, char name[]);
//删除联系人信息
void DelContact(struct Contact* pc);
//查找某个人的信息
void SearchContact(struct Contact* pc);
//修改联系人信息
void ModifyContact(struct Contact* pc);
contact.c
#include"contact.h"
//初始化通讯录
void InitContact(struct Contact* pc)
{
pc->sz = 0;
memset(pc->data, 0,sizeof(pc->data));
//数组名表示首元素地址,pc->data也表示首元素地址
}
//增加联系人
void AddContact(struct Contact* pc)
{
//判断通讯录是否有空间
if (pc->sz == MAX)
{
printf("通讯录已满,无法添加\n");
return;//结束函数
}
//增加一个人的信息
printf("请输入名字:->\n");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别:->\n");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:->\n");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入电话:->\n");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:->\n");
scanf("%s", pc->data[pc->sz].address);
pc->sz++;
printf("添加成功\n");
}
//打印联系人
void PrintContact(const struct Contact* pc)
{
int i = 0;
//打印标题
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n","名字","性别","年龄","电话","地址");
//打印信息
for (i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\n", pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].tele,
pc->data[i].address);
}
}
//查找某个人是否存在
static int FindByname(struct Contact* pc, char name[])//static修饰函数时,函数只能在自己源文件中看到,别人看不到,可以保护函数
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
return i;//找到就返回它的下标
}
return -1;//找不到
}
//删除某个人的信息
void DelContact(struct Contact* pc)
{
//通讯录不为空才能删除
if (pc->sz == 0)
{
printf("通讯录为空,无需删除\n");
return;
}
char name[MAXE_NAME];//要声明一下,否则后面报错
printf("请输入要删除人的名字:->\n");
scanf("%s", name);
//查找某个人是否存在
int pos=FindByname(pc,name);
if (pos == -1)
{
printf("要删除的人不存在\n");
return;
}
//如果存在,删除
int i = 0;
for (i = pos; i < pc->sz-1; i++)
{
pc->data[i] = pc->data[i+1];
}
pc->sz--;
printf("删除成功\n");
}
//查找某个人的信息
void SearchContact(struct Contact* pc)
{
char name[MAXE_NAME];//={0};
printf("请输入要查找人的名字:->\n");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
else
{
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "性别", "年龄", "电话", "地址");
printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\n", pc->data[pos].name,
pc->data[pos].sex,
pc->data[pos].age,
pc->data[pos].tele,
pc->data[pos].address);
}
}
//修改联系人信息
void ModifyContact(struct Contact* pc)
{
char name[MAXE_NAME];//={0};
printf("请输入要修改人的名字:->\n");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要修改的人不存在\n");
return;
}
else
{
//修改一个人的信息
printf("请输入名字:->\n");
scanf("%s", pc->data[pos].name);
printf("请输入性别:->\n");
scanf("%s", pc->data[pos].sex);
printf("请输入年龄:->\n");
scanf("%d", &(pc->data[pos].age));
printf("请输入电话:->\n");
scanf("%s", pc->data[pos].tele);
printf("请输入地址:->\n");
scanf("%s", pc->data[pos].address);
//pc->sz++;修改不会影响元素个数,不要动
printf("修改成功\n");
}
}
版本2 - 动态版本
动态版本,就是通讯录满了,会自动增容,(在一定的总空间大小下,不能无限增加),以储存新的联系人。
动态版本的优点:刚开始我们可能为了节省内存,将容量设置为50人,但是认识的人越来越多,联系人可能超过50人,动态版本的通讯录就会自动增加。动态版本不仅在一定程度上节省了空间,而且通讯录满了,还能自动增容,比静态通讯录更灵活。
思路:
静态通讯录转变为动态通讯录,基本框架是不变的。
主要发生改变的是,涉及动态内存的:
- 通讯录类型定义、创建,初始化
- 增加联系人函数的定义
- 如何退出通讯录(动态内存开辟,必然涉及空间回收,否则有内存泄漏的风险)
完整代码:
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
//动态版本
//1.通讯录初始化后,能存放3个人的信息
//2.当空间存放满时,增加2个信息,再满的时候,再增加两个信息
//3+2+2+2+2+2……
void meau()
{
printf("****************************************\n");
printf("*********** 1.add 2.del ***********\n");
printf("*********** 3.serrch 4.modify ********\n");
printf("*********** 5.sort 6.print ********\n");
printf("************** 0.exit ****************\n");
printf("****************************************\n");
}
enum Option
{
EXIT,//0
ADD,//1
DEL,//2
SEARCH,//3
MODIFY,//4
SORT,//5
PRINT//6
};
int main()
{
int input = 0;//创建通讯录
struct Contact con;//通讯录
//初始化通讯录
//给data在堆区上申请一块连续的空间,sz=0,capacity=0
InitContact(&con);
do
{
meau();
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 SORT:
break;
case PRINT:
PrintContact(&con);
break;
case EXIT://销毁通讯录
//printf("退出通讯录\n");
DestoryContact(&con);
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
contact.h
#pragma once
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
//类型的定义
#define MAXE_NAME 20
#define MAX_SEX 10
#define MAX_DELE 12
#define MAX_ADDREES 30
#define MAX 1000
#define DEFAULT_SZ 3
#define INC_ADDR 2
struct PeoInfo
{
char name[MAXE_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_DELE];
char address[MAX_ADDREES];
}PeoInfo;
//通讯录
struct Contact
{
struct PeoInfo *data;//存放添加进来的人的信息
int sz;//记录当前通讯录中已有元素的个数
int capacity;//记录当前通讯录的最大容量
};
//初始化通讯录
void InitContact(struct Contact* pc);
//增加联系人
void AddContact(struct Contact* pc);
//打印联系人信息
void PrintContact(const struct Contact* pc);//只打印,不修改,加上const,可以防止不小心修改,更安全
//查找某个人是否存在
int FindByname(struct Contact* pc, char name[]);
//删除联系人信息
void DelContact(struct Contact* pc);
//查找某个人的信息
void SearchContact(struct Contact* pc);
//修改联系人信息
void ModifyContact(struct Contact* pc);
//销毁通讯录
void DestoryContact(struct Contact* pc);
contact.c
#include"contact.h"
//初始化通讯录
void InitContact(struct Contact* pc)
{
pc->data = (struct PeoInfo*)malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
if (pc->data == NULL)
{
perror("InitContact");
return;
}
pc->sz = 0;
pc->capacity = MAX_ADDREES;
}
//增加联系人
void AddContact(struct Contact* pc)
{
//考虑增容
if (pc->sz == pc->capacity)
{
struct PeoInfo*ptr =(struct PeoInfo*) realloc(pc->data, (pc->capacity+ INC_ADDR)*sizeof(struct PeoInfo));
if (ptr != NULL)
{
pc->data = ptr;
pc->capacity += INC_ADDR;//容量增加
printf("增容成功\n");
}
else
{
perror("AddContact");
printf("增加联系人失败\n");
return;
}
}
//增加一个人的信息
printf("请输入名字:->\n");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别:->\n");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:->\n");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入电话:->\n");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:->\n");
scanf("%s", pc->data[pc->sz].address);
pc->sz++;
printf("添加成功\n");
}
//打印联系人
void PrintContact(const struct Contact* pc)
{
int i = 0;
//打印标题
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n","名字","性别","年龄","电话","地址");
//打印信息
for (i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\n", pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].tele,
pc->data[i].address);
}
}
//查找某个人是否存在
static int FindByname(struct Contact* pc, char name[])//static修饰函数时,函数只能在自己源文件中看到,别人看不到,可以保护函数
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
return i;//找到就返回它的下标
}
return -1;//找不到
}
//删除某个人的信息
void DelContact(struct Contact* pc)
{
//通讯录不为空才能删除
if (pc->sz == 0)
{
printf("通讯录为空,无需删除\n");
return;
}
char name[MAXE_NAME];//要声明一下,否则后面报错
printf("请输入要删除人的名字:->\n");
scanf("%s", name);
//查找某个人是否存在
int pos=FindByname(pc,name);
if (pos == -1)
{
printf("要删除的人不存在\n");
return;
}
//如果存在,删除
int i = 0;
for (i = pos; i < pc->sz-1; i++)
{
pc->data[i] = pc->data[i+1];
}
pc->sz--;
printf("删除成功\n");
}
//查找某个人的信息
void SearchContact(struct Contact* pc)
{
char name[MAXE_NAME];//={0};
printf("请输入要查找人的名字:->\n");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
else
{
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "性别", "年龄", "电话", "地址");
printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\n", pc->data[pos].name,
pc->data[pos].sex,
pc->data[pos].age,
pc->data[pos].tele,
pc->data[pos].address);
}
}
//修改联系人信息
void ModifyContact(struct Contact* pc)
{
char name[MAXE_NAME];//={0};
printf("请输入要修改人的名字:->\n");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要修改的人不存在\n");
return;
}
else
{
//修改一个人的信息
printf("请输入名字:->\n");
scanf("%s", pc->data[pos].name);
printf("请输入性别:->\n");
scanf("%s", pc->data[pos].sex);
printf("请输入年龄:->\n");
scanf("%d", &(pc->data[pos].age));
printf("请输入电话:->\n");
scanf("%s", pc->data[pos].tele);
printf("请输入地址:->\n");
scanf("%s", pc->data[pos].address);
//pc->sz++;修改不会影响元素个数,不要动
printf("修改成功\n");
}
}
//销毁通讯录
void DestoryContact(struct Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->capacity = 0;
}
开辟动态内存的函数:http://t.csdn.cn/9CTKN
版本3 - 文件版本
动态版本虽然满足了灵活添加联系人的要求,但是我们每次保存完信息,下次再打开程序,上次保存的通讯人信息就没有了,那么如何解决这个这个问题呢?
(建议学完文件后再来阅读这一版本通讯录。)
可以通过文件解决。
思路:
退出通讯录之前,把联系人信息保存到一个文件中(此处文件名为:contact.dat)
打开通讯录后,在初始化函数这一阶段,读取上次保存在文件中的联系人信息,输入到程序中的通讯录中。
这样就满足了通讯录的保存功能。
完整代码:
test.c
#include"contact.h"
// 版本3
//当通讯录退出时,把信息写到文件
// 当通讯录初始化时,加载文件的信息到通讯录中
//
//
void meau()
{
printf("****************************************\n");
printf("*********** 1.add 2.del ***********\n");
printf("*********** 3.serrch 4.modify ********\n");
printf("*********** 5.sort 6.print ********\n");
printf("************** 0.exit ****************\n");
printf("****************************************\n");
}
enum Option
{
EXIT,//0
ADD,//1
DEL,//2
SEARCH,//3
MODIFY,//4
SORT,//5
PRINT//6
};
int main()
{
int input = 0;//创建通讯录
struct Contact con;//通讯录
//初始化通讯录
//给data在堆区上申请一块连续的空间,sz=0,capacity=0
InitContact(&con);
do
{
meau();
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 SORT:
break;
case PRINT:
PrintContact(&con);
break;
case EXIT:
//保存信息到文件
SaveContact(&con);
//销毁通讯录
DestoryContact(&con);
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
contact.h
#pragma once
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
//类型的定义
#define MAXE_NAME 20
#define MAX_SEX 10
#define MAX_DELE 12
#define MAX_ADDREES 30
#define MAX 1000
#define DEFAULT_SZ 3
#define INC_ADDR 2
struct PeoInfo
{
char name[MAXE_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_DELE];
char address[MAX_ADDREES];
}PeoInfo;
//通讯录
struct Contact
{
struct PeoInfo *data;//存放添加进来的人的信息
int sz;//记录当前通讯录中已有元素的个数
int capacity;//记录当前通讯录的最大容量
};
//初始化通讯录
void InitContact(struct Contact* pc);
//增加联系人
void AddContact(struct Contact* pc);
//打印联系人信息
void PrintContact(const struct Contact* pc);//只打印,不修改,加上const,可以防止不小心修改,更安全
//查找某个人是否存在
int FindByname(struct Contact* pc, char name[]);
//删除联系人信息
void DelContact(struct Contact* pc);
//查找某个人的信息
void SearchContact(struct Contact* pc);
//修改联系人信息
void ModifyContact(struct Contact* pc);
//销毁通讯录
void DestoryContact(struct Contact* pc);
//保存信息到文件
void SaveContact(struct Contact* pc);
//加载文件
void LoadContact(struct Contact* pc);
//考虑增容
void CheckCapacity(struct Contact* pc);
contact.c
#include"contact.h"
//加载文件
void LoadContact(struct Contact* pc)
{
//打开文件
FILE* pf = fopen("contact.dat", "r");
if (pf == NULL)
{
perror("LoadContact");
return;
}
//读文件
struct PeoInfo tmp = { 0 };
while (fread(&tmp, sizeof(struct PeoInfo), 1, pf))
{
//是否需要增容
CheckCapacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
//初始化通讯录
void InitContact(struct Contact* pc)
{
pc->data = (struct PeoInfo*)malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
if (pc->data == NULL)
{
perror("InitContact");
return;
}
pc->sz = 0;
pc->capacity = MAX_ADDREES;
//加载文件
LoadContact(pc);
}
//考虑增容
void CheckCapacity(struct Contact* pc)
{
if (pc->sz == pc->capacity)
{
struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + INC_ADDR) * sizeof(struct PeoInfo));
if (ptr != NULL)
{
pc->data = ptr;
pc->capacity += INC_ADDR;//容量增加
printf("增容成功\n");
}
else
{
perror("AddContact");
printf("增加联系人失败\n");
return;
}
}
}
//增加联系人
void AddContact(struct Contact* pc)
{
//考虑增容
CheckCapacity(pc);
//增加一个人的信息
printf("请输入名字:->\n");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别:->\n");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:->\n");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入电话:->\n");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:->\n");
scanf("%s", pc->data[pc->sz].address);
pc->sz++;
printf("添加成功\n");
}
//打印联系人
void PrintContact(const struct Contact* pc)
{
int i = 0;
//打印标题
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n","名字","性别","年龄","电话","地址");
//打印信息
for (i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\n", pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].tele,
pc->data[i].address);
}
}
//查找某个人是否存在
static int FindByname(struct Contact* pc, char name[])//static修饰函数时,函数只能在自己源文件中看到,别人看不到,可以保护函数
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
return i;//找到就返回它的下标
}
return -1;//找不到
}
//删除某个人的信息
void DelContact(struct Contact* pc)
{
//通讯录不为空才能删除
if (pc->sz == 0)
{
printf("通讯录为空,无需删除\n");
return;
}
char name[MAXE_NAME];//要声明一下,否则后面报错
printf("请输入要删除人的名字:->\n");
scanf("%s", name);
//查找某个人是否存在
int pos=FindByname(pc,name);
if (pos == -1)
{
printf("要删除的人不存在\n");
return;
}
//如果存在,删除
int i = 0;
for (i = pos; i < pc->sz-1; i++)
{
pc->data[i] = pc->data[i+1];
}
pc->sz--;
printf("删除成功\n");
}
//查找某个人的信息
void SearchContact(struct Contact* pc)
{
char name[MAXE_NAME];//={0};
printf("请输入要查找人的名字:->\n");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
else
{
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "性别", "年龄", "电话", "地址");
printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\n", pc->data[pos].name,
pc->data[pos].sex,
pc->data[pos].age,
pc->data[pos].tele,
pc->data[pos].address);
}
}
//修改联系人信息
void ModifyContact(struct Contact* pc)
{
char name[MAXE_NAME];//={0};
printf("请输入要修改人的名字:->\n");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要修改的人不存在\n");
return;
}
else
{
//修改一个人的信息
printf("请输入名字:->\n");
scanf("%s", pc->data[pos].name);
printf("请输入性别:->\n");
scanf("%s", pc->data[pos].sex);
printf("请输入年龄:->\n");
scanf("%d", &(pc->data[pos].age));
printf("请输入电话:->\n");
scanf("%s", pc->data[pos].tele);
printf("请输入地址:->\n");
scanf("%s", pc->data[pos].address);
//pc->sz++;修改不会影响元素个数,不要动
printf("修改成功\n");
}
}
//销毁通讯录
void DestoryContact(struct Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->capacity = 0;
}
//保存信息到文件
void SaveContact(struct Contact* pc)
{
//打开文件
FILE* pf = fopen("contact.dat", "w");
if (pf == NULL)
{
perror("SaveContact");
return;
}
//写文件
int i = 0;
for (i = 0; i < pc->sz; i++)
{
fwrite(pc->data + i, sizeof(struct PeoInfo), 1, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}