在学习C语言的过程中,为了检验C语言结构体学的如何,我们利用结构体的知识来做一个通讯录管理系统。
一.通讯录框架信息
构建通讯录管理系统我们所需要知道的:
1.人的信息:姓名,年龄,性别,地址,电话
2.通讯录中可以存放多少人的信息(例:100人)
3.通讯录可以使用的功能(这里列举几项):
->1.增加联系人
->2.删除联系人
->3.查找联系人
->4.显示通讯录
->5.修改指定联系人
->6.清空通讯录
二.框架的构建
1.创建菜单
为了将通讯录的功能全部的展现出来以及更好的管理通讯录系统,这里我们创建了菜单,使用者可以根据需求来使用不同的功能
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("*** 7.empty 8.exit ***\n");
printf("*************************\n");
}
2.成员信息的创建
因为我们需要创建成员的信息和通讯录中成员的数量,所以我们需要两个结构体来创建:一个是存放人的信息,另一个是当前已放信息的个数
typedef struct PoeInfo //通讯录成员的信息
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char addr[ADDR_MAX];
char tele[TELE_MAX];
}PeoInfo;
静态版本:
typedef struct contast
{
PeoInfo data[MAX]; //存放人的信息
int sz; //当前已放信息的个数
}contast;
动态版本:
typedef struct contast
{
PeoInfo* data; //存放人的信息
int sz; //存放信息的个数
int capacity; //容量
}contast;
3.菜单功能声明
//增加联系人
void AddContast(contast* pc);
//删除联系人
void DelContast(contast* pc);
//查找指定联系人的信息
void SearchContast(contast* pc);
//修改指定联系人的信息
void ModifyContast(contast* pc);
//显示所有联系人的信息
void ShowContast(contast* pc);
//给通讯录排序
void SortContast(contast* pc);
//清空通讯录
void EmptyContast(contast* pc);
动态版本:新加了通讯录销毁功能(释放向系统申请的空间)
//销毁通讯录
void DestoryContast(contast* pc);
三.通讯录功能的实现
1.初始化通讯录
void InitContast(contast* pc)
{
assert(pc);
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
动态版本:
void InitContast(contast* pc)
{
assert(pc);
pc->sz = 0;
PeoInfo* ptr = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
if(ptr == NULL)
{
printf("%s", strerror(errno));
return;
}
pc->data = ptr;
pc->capacity = DEFAULT_SZ;
}
2.增加联系人
void AddContast(contast* 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].addr );
printf("请输入电话号:>");
scanf("%s", pc->data[pc->sz].tele );
pz->sz++;
}
动态版本:
//增加容量
void check_capacity(contast* pc)
{
assert(pc);
if(pc->sz == pc->capacity)
{
PeoInfo* ptr = (*PeoInfo)realloc(pc->data, (capacity + DEFAULT_SZ) + sizeof(PeoInfo));
if(ptr == NULL)
{
perror("cheak_capacity::realloc");
return;
}
pc->data = ptr;
pc->capacity += 2;
printf("增容成功\n");
}
}
void AddContast(contast* pc)
{
assert(pc);
check_capacity(pc);
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].addr );
printf("请输入电话号:>");
scanf("%s", pc->data[pc->sz].tele );
pz->sz++;
}
3.删除指定联系人
(1).寻找该成员
int FindByName(contast* ps, char* p)
{
assert(ps && p);
int i = 0;
for(; i < ps->sz; i++)
{
if(strcmp(ps->data[i].name, p) == 0)
return i;
}
return -1;
}
(2).删除该成员
void DelContast(contast* pc)
{
assert(pc);
if(pc->sz == 0)
{
printf("没有该成员\n");
return;
}
char name[NAME_MAX] = {0};
int del = FindByName(pc->data, name);
if(del == -1)
{
printf("没有该成员\n");
return;
}
int i = 0;
for(i = del; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
}
4.查找指定联系人
void SearchContast(contast* pc)
{
assert(pc);
if(pc->sz == 0)
{
printf("通讯录没有成员\n");
return;
}
char name[NAME_MAX] = 0;
printf("请输入你要查看的成员姓名:");
scanf("%s", name);
int pos = FindByName(pc->data, name);
if(pos == -1)
{
printf("没有该成员,无法查看\n");
return;
}
printf("%-20s\t%-5s\t%-4s\t%-20s\t%-12s\n", "姓名","年纪","性别","地址","电话号码");
printf("%-20s\t%-5d\t%-4s\t%-20s\t%-12s\n", pc->data[pos].name
, pc- >data[pos].age
, pc->data[pos].sex
, pc->data[pos].addr
, pc->data[pos].tele);
}
5.显示所有联系人
void ShowContast(contast* pc)
{
assert(pc);
if(pc->sz == 0)
{
printf("通讯录没有成员,无法查看\n");
return;
}
int i = 0;
printf("%-20s\t%-5s\t%-4s\t%-20s\t%-12s\n", "姓名", "年纪", "性别", "地址", "电话号码");
for(i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5d\t%-4s\t%-20s\t%-12s\n", pc->data[i].name
, pc->data[i].age
, pc->data[i].gender
, pc->data[i].add
, pc->data[i].tele)
}
}
6.修改指定联系人
void Modifycontast(contast* pc)
{
assert(pc);
if(pc->sz == 0)
{
printf("通讯录没有成员,无法进行修改\n");
return;
}
char name[NAME_MAX] = {0};
printf("请输入修改人的姓名:");
scanf("%s", name);
int pos = FindByName(pc->data, name);
if(pos == -1)
{
printf("没有该联系人\n");
return;
}
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].addr );
printf("请输入电话号:>");
scanf("%s", pc->data[pos].tele );
}
7.给通讯录排序(根据姓名来排序)
void SortContast(contast* pc)
{
assert(pc);
if(pc->sz == 0)
{
printf("通讯录没有成员,无法排序\n");
return;
}
qsort( pc->data,
pc->sz,
sizeof(pc->data[0]),
cmp_data_PeoInfo_name );
printf("排列结束\n");
}
int cmp_data_PeoInfo_name(void* e1, void* e2)
{
return strcmp(((*contast)e1)->name, ((*contast)e2)->name);
}
8.清空所有联系人
void EmptyContast(contast* pc)
{
assert(pc);
int i = 0;
if(pc->sz == 0)
{
printf("通讯录为空,没有成员可删除\n");
return;
}
Initcontast(pc); // 或pc->sz = 0 memset(pc->data, 0, sizeof(pc->data));
printf("清空完毕\n");
}
动态版本:
9.通讯录的销毁
void DestoryContast(contast* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
pc = NULL //将pc置空也可以
}
四.完整代码
创建三个文件,test.c- 测试,contast.h - 函数的声明, contast.c - 函数的定义
test.c
#include "contast.h"
void menu()
{
printf("*************************");
printf("**** 通讯录管理系统 ****");
printf("*** 1.Add 2.Del ***");
printf("*** 3.Search 4.Modify **");
printf("*** 5.Show 6.SorT ***");
printf("*** 7.empty 0.exit ***");
printf("*************************");
}
int main()
{
int input = 0;
contast con;
Initcontast(&con); //结构体contast初始化
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch(input)
{
case Add:
AddContast(&con);
break;
case Del:
DelContast(&con);
break;
case Search:
SearchContast(&con);
break;
case Modify:
ModifyContast(&con);
break;
case Show5:
ShowContast(&con);
break;
case Sort:
SortContast(&con);
break;
case Empty:
EmptyContast(&con);
break;
case Exit:
printf("退出程序");
break;
default:
DestoryContast(&con); //动态版本才有
printf("没有该指令,请重新输入");
break
}
}while(input);
return 0;
}
contast.h
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define MXA 100
#define NAME_MAX 20
#define ADDR_MAX 30
#define SEX_MAX 5
#define TELE_MAX 20
//动态版本增加的两个宏
#define DEFAULT_SZ 3
#define INC_SZ 2
typedef struct PoeInfo //通讯录成员的信息
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char addr[ADDR_MAX];
char tele[TELE_MAX];
}PeoInfo;
typedef struct contast //通讯录成员总数
{
PeoInfo data[MAX]; //通讯录的容量
int sz; //现成员的个数
}contast;
enum Function
{
Exit,
Add,
Del,
Search,
Modify,
Show,
Sort,
Empty
}; //将功能枚举出来
//增加联系人
void AddContast(contast* pc);
//删除联系人
void DelContast(contast* pc);
//查找指定联系人的信息
void SearchContast(contast* pc);
//修改指定联系人的信息
void ModifyContast(contast* pc);
//显示所有联系人的信息
void ShowContast(contast* pc);
//给通讯录排序
void SortContast(contast* pc);
//清空通讯录
void EmptyContast(contast* pc);
contast.c
#include "contast.h"
//通讯录初始化(静态版本)
void InitContast(contast* pc)
{
assert(pc);
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
//通讯录初始化(动态版本)
void InitContast(contast* pc)
{
assert(pc);
pc->sz = 0;
PeoInfo* ptr = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
if(ptr == NULL)
{
printf("%s", strerror(errno));
return;
}
pc->data = ptr;
pc->capacity = DEFAULT_SZ;
}
//增加联系人(静态版本)
void AddContast(contast* 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].addr );
printf("请输入电话号:>");
scanf("%s", pc->data[pc->sz].tele );
pz->sz++;
}
//增加联系人(动态版本)
//增加容量
void check_capacity(contast* pc)
{
assert(pc);
if(pc->sz == pc->capacity)
{
PeoInfo* ptr = (*PeoInfo)realloc(pc->data, (capacity + DEFAULT_SZ) + sizeof(PeoInfo));
if(ptr == NULL)
{
perror("cheak_capacity::realloc");
return;
}
pc->data = ptr;
pc->capacity += 2;
printf("增容成功\n");
}
}
void AddContast(contast* pc)
{
assert(pc);
check_capacity(pc);
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].addr );
printf("请输入电话号:>");
scanf("%s", pc->data[pc->sz].tele );
pz->sz++;
}
//寻找指定姓名
int FindByName(contast* ps, char* p)
{
assert(ps && p);
int i = 0;
for(; i < ps->sz; i++)
{
if(strcmp(ps->data[i].name, p) == 0)
return i;
}
return -1;
}
//删除指定联系人
void DelContast(contast* pc)
{
assert(pc);
if(pc->sz == 0)
{
printf("没有该成员");
return;
}
char name[NAME_MAX] = {0};
int del = FindByName(pc->data, name);
if(del == -1)
{
printf("没有该成员");
return;
}
int i = 0;
for(i = del; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
}
//寻找指定联系人
void SearchContast(contast* pc)
{
assert(pc);
if(pc->sz == 0)
{
printf("通讯录没有成员");
return;
}
char name[NAME_MAX] = 0;
printf("请输入你要查看的成员姓名:");
scanf("%s", name);
int pos = FindByName(pc->data, name);
if(pos == -1)
{
printf("没有该成员,无法查看");
return;
}
printf("%-20s\t%-5s\t%-4s\t%-20s\t%-12s\n", "姓名","年纪","性别","地址","电话号码");
printf("%-20s\t%-5d\t%-4s\t%-20s\t%-12s\n", pc->data[pos].name
, pc- >data[pos].age
, pc->data[pos].sex
, pc->data[pos].addr
, pc->data[pos].tele);
}
//显示所以联系人
void ShowContast(contast* pc)
{
assert(pc);
if(pc->sz == 0)
{
printf("通讯录没有成员,无法查看");
return;
}
int i = 0;
printf("%-20s\t%-5s\t%-4s\t%-20s\t%-12s\n", "姓名", "年纪", "性别", "地址", "电话号码");
for(i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5d\t%-4s\t%-20s\t%-12s\n", pc->data[i].name
, pc->data[i].age
, pc->data[i].gender
, pc->data[i].add
, pc->data[i].tele)
}
}
//修改指定联系人
void Modifycontast(contast* pc)
{
assert(pc);
if(pc->sz == 0)
{
printf("通讯录没有成员,无法进行修改");
return;
}
char name[NAME_MAX] = {0};
printf("请输入修改人的姓名:");
scanf("%s", name);
int pos = FindByName(pc->data, name);
if(pos == -1)
{
printf("没有该联系人");
return;
}
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].addr );
printf("请输入电话号:>");
scanf("%s", pc->data[pos].tele );
}
//给通讯录排序(根据姓名)
int cmp_data_PeoInfo_name(const void* e1, const void* e2)
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContast(contast* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录没有成员,无法排序\n");
return;
}
qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_data_PeoInfo_name);
printf("排序完成\n");
int i = 0;
printf("%-20s\t%-5s\t%-4s\t%-20s\t%-12s\n", "姓名", "年纪", "性别", "地址", "电话号码");
for (i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5d\t%-4s\t%-20s\t%-12s\n", pc->data[i].name
, pc->data[i].age
, pc->data[i].sex
, pc->data[i].addr
, pc->data[i].tele);
}
}
//清空所有联系人
void EmptyContast(contast* pc)
{
assert(pc);
int i = 0;
if(pc->sz == 0)
{
printf("通讯录为空,没有成员可删除");
return;
}
Initcontast(pc); // 或pc->sz = 0 memset(pc->data, 0, sizeof(pc->data));
printf("清空完毕\n");
}
//动态版本
//释放申请的空间
void DestoryContast(contast* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
pc = NULL;
}
以上就是通讯录完整代码,有兴趣的可以观摩一下,它可以加深我们对结构体的掌握