我奶奶都能学会的【C语言】动态版本通讯录,你们还不是手到擒来
作者有一个通讯录思维导图可以看一下,在静态版里
通讯录静态版:http://t.csdn.cn/HxO7I
目录
1.功能分析
要实现的功能有:增加联系人信息、删除联系人信息、查找联系人信息、修改联系人信息、显示联系人信息、对联系人的信息进行排序、通讯录满了自动增加空间。
2.程序框架
程序分为test.c、contact.c两个源文件和contact.h一个头文件。
test.c:主函数接口引入。
contact.c:函数主要实现
contact.h:头文件引入、函数声明、结构体声明。
3.代码模块
3.1 main函数代码呈现
int main()
{
int input = 0;
contact con;//通讯录
//初始化通讯录
in_it_contact(&con);
do
{
menu();//打印菜单函数
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case EXIT:
destory_contact(&con);//销毁
printf("退出通讯录n");
break;
case ADD:
add_contact(&con);//添加联系人信息函数
break;
case DEL:
del_contact(&con);//删除联系人信息函数
break;
case SERCH:
search_contact(&con);//搜索指定联系人信息函数
break;
case MODIFY:
modify_contact(&con);//修改指定联系人信息函数
break;
case SHOW:
show_contact(&con);//展示联系人信息函数
break;
case SORT:
sort_contact(&con);//排序联系人信息函数
break;
default:
printf("选择错误,请重新选择n");
break;
}
} while (input);
分析:主要是引入函数的接口,此处用了常见的do while循环,并且将input变量作为while()后面括号中的条件,此处是一个极其巧妙的运用,当input变量为0时循环结束,程序终止,此时也与前面的switch和case进行了一一对应。
3.2 菜单函数
void menu()
{
printf("*********>>>>>>> 通讯录选择菜单 <<<<<<*********n");
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");
}
使用printf来输出提示玩家的信息,* 可以是打印内容看起来简洁美观
3.3 初始化功能
int in_it_contact(contact* pc)//初始化
{
assert(pc);
pc->count = 0;//将pc指向的count
pc -> date = (people*)calloc(3, sizeof(people));
//判断是否为空指针
if (NULL == pc -> date)
{
printf("in_it_contact:%sn", strerror(errno));//报错
return 1;
}
pc->capacity = DEFAULT_SZ;//#define定义的符号,值为3
return 0;
}
利用 calloc 动态内存函数开辟3个空间给通讯录,也就是说通讯录的初始空间为3,可以存放3个人的信息,若超过了3个人,在考虑扩容。
3.4 添加联系人
void check_capacity(contact* pc)//增容函数的实现
{
if (pc->count == pc->capacity)
{
//realloc总的空间等于先开辟的空间+后开辟的空间
//INC_SZ是定义的符号,值为2 - 一次性扩容2个空间
people* ptr = (people*)realloc(pc->date, (pc->capacity + INC_SZ) * sizeof(people));
//判断是否为空指针
if (NULL == ptr)
{
printf("add_contact:%sn", strerror(errno));//报错
return;
}
else
{
pc->date = ptr;
pc->capacity += INC_SZ;
printf("增容成功n");
}
}
}
//动态版本
void add_contact(contact* pc)//添加
{
assert(pc);
//增容
check_capacity(pc);//增容函数
printf("请输入姓名:");
scanf("%s", pc->date[pc->count].name);
printf("请输入年龄:");
scanf("%d", &pc->date[pc->count].age);
printf("请输入性别:");
scanf("%s", pc->date[pc->count].sex);
printf("请输入电话:");
scanf("%s", pc->date[pc->count].tele);
printf("请输入地址:");
scanf("%s", pc->date[pc->count].addr);
pc->count++;
printf("添加成功n");
}
首先分情况讨论,如果初始的3个空间满了。则开始扩容,并且每次增加两个空间;如果没满就开始输入联系人的信息。
3.5 删除联系人信息
void del_contact(contact* pc)//删除
{
char name[MAX_Name] = { 0 };
assert(pc);
if (pc->count == 0)
{
printf("通讯录为空,没有信息可以删除n");
return;
}
printf("请输入要删除的姓名:");
scanf("%s", name);
//1.查找
int ret = find_by_name(pc, name);//查找联系人姓名的函数
if (-1 == ret)
{
printf("要删除的人不存在n");
return;
}
//2.删除
int i = 0;
for (i = ret; i < pc->count - 1; i++)
{
pc->date[i] = pc->date[i + 1];
}
pc->count--;
printf("删除成功n");
}
分析:删除操作并不复杂,就是先查找到我们想要删除的那个联系人,然后将这个联系人后面的信息逐个向前进行覆盖,同时将记录联系人数目的变量count的值进行减1。
3.6 搜索联系人
void search_contact(contact* pc)//搜索
{
assert(pc);
char name[MAX_Name] = { 0 };
if (pc->count == 0)
{
printf("通讯录为空,没有信息可以搜索n");
return;
}
printf("请输入要搜索的姓名:");
scanf("%s", name);
//1.查找
int ret = find_by_name(pc, name);
if (-1 == ret)
{
printf("要搜索的人不存在n");
return;
}
//2.展示
printf("%-20st%-5st%-5st%-12st%-30sn", "姓名", "年龄", "性别", "电话", "地址");
printf("%-20st%-5dt%-5st%-12st%-30sn", pc->date[ret].name,
pc->date[ret].age,
pc->date[ret].sex,
pc->date[ret].tele,
pc->date[ret].addr);
}
分析:如果找到了就打印出联系人的信息,找不到就提示找不到。
3.7 查找函数的实现
int find_by_name(contact* pc, char name[])//查找
{
assert(pc);
int i = 0;
for (i = 0; i < pc->count; i++)
{
if (0 == strcmp(pc->date[i].name, name))
{
return i;
}
}
return -1;
}
分析:此处查找函数是通过遍历联系人中的信息进行实现的,当我们想查找的联系人的信息与某个联系人的信息一致时就停止下来,如果能够找到就返回其对应的下标,如果找不到就返回-1。
3.8 修改联系人信息
void modify_contact(contact* pc)//修改
{
assert(pc);
char name[MAX_Name] = { 0 };
if (pc->count == 0)
{
printf("通讯录为空,没有信息可以修改n");
return;
}
printf("请输入要修改的姓名:");
scanf("%s", name);
//1.查找
int ret = find_by_name(pc, name);
if (-1 == ret)
{
printf("要修改的人不存在n");
return;
}
//2.修改
printf("要修改的人的信息已经查找到,接下来开始修改n");
printf("请输入修改后的姓名:");
scanf("%s", pc->date[ret].name);
printf("请输入修改后的年龄:");
scanf("%d", &pc->date[ret].age);
printf("请输入修改后的性别:");
scanf("%s", pc->date[ret].sex);
printf("请输入修改后的电话:");
scanf("%s", pc->date[ret].tele);
printf("请输入修改后的地址:");
scanf("%s", pc->date[ret].addr);
printf("修改成功n");
}
分析:先找到要修改的人,然后修改;若找不到,就提示不存在。修改其实就是重新输入一遍信息
3.9 打印联系人信息
void show_contact(const contact* pc)//展示
{
assert(pc);
int i = 0;
printf("%-20st%-5st%-5st%-12st%-30sn", "姓名", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->count; i++)
{
printf("%-20st%-5dt%-5st%-12st%-30sn", pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].addr);
}
}
分析:利用一个循环,将通讯录中的信息打印出来
3.9.1 对联系人的信息进行排序
int cmp_peo_by_age(const void* e1, const void* e2)//按照年龄排序
{
return ((people*)e1)->age - ((people*)e2)->age;
}
void sort_contact(contact* pc)//排序
{
//按照年龄排序
qsort(pc->date, pc->count, sizeof(people), cmp_peo_by_age);
printf("排序成功n");
}
分析:这里是利用qsort快速排序的函数,按照年龄升序排的。
3.9.2 空间释放函数
void destory_contact(contact* pc)//销毁
{
assert(pc);
free(pc->date);
pc->date = NULL;
}
开辟的空间使用完要及时归还给操作系统,所以要对空间进行释放。
4.代码运行结果
5.完整代码展示
5.1 contact.h
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<errno.h>
#define DEFAULT_SZ 3
#define INC_SZ 2
#define MAX 1000
#define MAX_Name 20
#define MAX_Sex 10
#define MAX_Tele 12
#define MAX_Addr 20
//使用typedef对类型重命名
typedef struct people//人的信息
{
char name[MAX_Name];//名字
int age;//年龄
char sex[MAX_Sex];//性别
char tele[MAX_Tele];//电话
char addr[MAX_Addr];//地址
} people;
//动态版本
//通讯录的信息
typedef struct contact
{
people* date;//存放1000个人的信息
//count - 随着信息的存入或删除而增加或减少
int count;//记录当天通讯录中的实际人数
int capacity;//当前通讯录的容量
} contact;
int in_it_contact(contact* pc);//初始化通讯录函数的声明
void destory_contact(contact* pc);//销毁函数
void add_contact(contact* pc);//添加联系人信息函数的声明
void show_contact(const contact* pc);//展示联系人信息函数
void del_contact(contact* pc);//删除联系人信息的函数
void search_contact(contact* pc);//搜索指定联系人的函数
void modify_contact(contact* pc);//修改指定联系人信息的函数
void sort_contact(contact* pc);//排序联系人的函数
5.2 contact.c
#include"contact.h"
//动态版本
int in_it_contact(contact* pc)//初始化
{
assert(pc);
pc->count = 0;//将pc指向的count
pc -> date = (people*)calloc(3, sizeof(people));
//判断是否为空指针
if (NULL == pc -> date)
{
printf("in_it_contact:%sn", strerror(errno));//报错
return 1;
}
pc->capacity = DEFAULT_SZ;//#define定义的符号,值为3
return 0;
}
void destory_contact(contact* pc)//销毁
{
assert(pc);
free(pc->date);
pc->date = NULL;
}
void check_capacity(contact* pc)//增容函数的实现
{
if (pc->count == pc->capacity)
{
//realloc总的空间等于先开辟的空间+后开辟的空间
people* ptr = (people*)realloc(pc->date, (pc->capacity + INC_SZ) * sizeof(people));
//判断是否为空指针
if (NULL == ptr)
{
printf("add_contact:%sn", strerror(errno));//报错
return;
}
else
{
pc->date = ptr;
pc->capacity += INC_SZ;
printf("增容成功n");
}
}
}
//动态版本
void add_contact(contact* pc)//添加
{
assert(pc);
//增容
check_capacity(pc);//增容函数
printf("请输入姓名:");
scanf("%s", pc->date[pc->count].name);
printf("请输入年龄:");
scanf("%d", &pc->date[pc->count].age);
printf("请输入性别:");
scanf("%s", pc->date[pc->count].sex);
printf("请输入电话:");
scanf("%s", pc->date[pc->count].tele);
printf("请输入地址:");
scanf("%s", pc->date[pc->count].addr);
pc->count++;
printf("添加成功n");
}
void show_contact(const contact* pc)//展示
{
assert(pc);
int i = 0;
printf("%-20st%-5st%-5st%-12st%-30sn", "姓名", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->count; i++)
{
printf("%-20st%-5dt%-5st%-12st%-30sn", pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].addr);
}
}
int find_by_name(contact* pc, char name[])//查找
{
assert(pc);
int i = 0;
for (i = 0; i < pc->count; i++)
{
if (0 == strcmp(pc->date[i].name, name))
{
return i;
}
}
return -1;
}
void del_contact(contact* pc)//删除
{
char name[MAX_Name] = { 0 };
assert(pc);
if (pc->count == 0)
{
printf("通讯录为空,没有信息可以删除n");
return;
}
printf("请输入要删除的姓名:");
scanf("%s", name);
//1.查找
int ret = find_by_name(pc, name);//查找联系人姓名的函数
if (-1 == ret)
{
printf("要删除的人不存在n");
return;
}
//2.删除
int i = 0;
for (i = ret; i < pc->count - 1; i++)
{
pc->date[i] = pc->date[i + 1];
}
pc->count--;
printf("删除成功n");
}
void search_contact(contact* pc)//搜索
{
assert(pc);
char name[MAX_Name] = { 0 };
if (pc->count == 0)
{
printf("通讯录为空,没有信息可以搜索n");
return;
}
printf("请输入要搜索的姓名:");
scanf("%s", name);
//1.查找
int ret = find_by_name(pc, name);
if (-1 == ret)
{
printf("要搜索的人不存在n");
return;
}
//2.展示
printf("%-20st%-5st%-5st%-12st%-30sn", "姓名", "年龄", "性别", "电话", "地址");
printf("%-20st%-5dt%-5st%-12st%-30sn", pc->date[ret].name,
pc->date[ret].age,
pc->date[ret].sex,
pc->date[ret].tele,
pc->date[ret].addr);
}
void modify_contact(contact* pc)//修改
{
assert(pc);
char name[MAX_Name] = { 0 };
if (pc->count == 0)
{
printf("通讯录为空,没有信息可以修改n");
return;
}
printf("请输入要修改的姓名:");
scanf("%s", name);
//1.查找
int ret = find_by_name(pc, name);
if (-1 == ret)
{
printf("要修改的人不存在n");
return;
}
//2.修改
printf("要修改的人的信息已经查找到,接下来开始修改n");
printf("请输入修改后的姓名:");
scanf("%s", pc->date[ret].name);
printf("请输入修改后的年龄:");
scanf("%d", &pc->date[ret].age);
printf("请输入修改后的性别:");
scanf("%s", pc->date[ret].sex);
printf("请输入修改后的电话:");
scanf("%s", pc->date[ret].tele);
printf("请输入修改后的地址:");
scanf("%s", pc->date[ret].addr);
printf("修改成功n");
}
int cmp_peo_by_age(const void* e1, const void* e2)//按照年龄排序
{
return ((people*)e1)->age - ((people*)e2)->age;
}
void sort_contact(contact* pc)//排序
{
//按照年龄排序
qsort(pc->date, pc->count, sizeof(people), cmp_peo_by_age);
printf("排序成功n");
}
5.3 test.c
//动态版本通讯录
//默认存放3个人的信息
//如果空间不够了就增加空间,每次增加2个人的空间
#include"contact.h"
void menu()
{
printf("*********>>>>>>> 通讯录选择菜单 <<<<<<*********n");
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");
}
enum option
{
EXIT,//0
ADD,//1
DEL,//2
SERCH,//3
MODIFY,//4
SHOW,//5
SORT//6
};
int main()
{
int input = 0;
contact con;//通讯录
//初始化通讯录
in_it_contact(&con);
do
{
menu();//打印菜单函数
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case EXIT:
destory_contact(&con);//销毁
printf("退出通讯录n");
break;
case ADD:
add_contact(&con);//添加联系人信息函数
break;
case DEL:
del_contact(&con);//删除联系人信息函数
break;
case SERCH:
search_contact(&con);//搜索指定联系人信息函数
break;
case MODIFY:
modify_contact(&con);//修改指定联系人信息函数
break;
case SHOW:
show_contact(&con);//展示联系人信息函数
break;
case SORT:
sort_contact(&con);//排序联系人信息函数
break;
default:
printf("选择错误,请重新选择n");
break;
}
} while (input);
return 0;
}