在学习完结构体知识后,我们就来一起写一个通讯录。
首先明确内容,我们要弄清楚我们要构建的通讯录可以保存1000的人的信息,其次通讯录要能增加联系人,删除联系人,同时要实现对联系人的修改,查找和排序,接着便是开始编写我们的代码
首先创建一个工程contact.h来存放所有的头文件,用结构体来编写我们要存放的内容
typedef struct PeoInfo
{
char name[NAME_MAX];
short age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
利用宏定义定义数组的大小来方便我们后期进行更改,利用typedef来方便我们引用结构体定义,定义好后,我们就来实现主函数的实现,创建工程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. clear **\n");
printf("** 7. sort 0. exit **\n");
printf("******************************\n");
}
int main()
{
int input = 0;
//创建通讯录
Contact con;//
//初始化通讯录
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch(input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case SEARCH:
FindContact(&con);
break;
case SORT:
SortContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case SHOW:
ShowContact(&con);
break;
case CLEAR:
ClearContact(&con);
break;
case EXIT:
printf("退出程序\n");
return 0;
default:
printf("输入有误,请重新输入\n");
break;
}
} while (input);
return 0;
}
现将之前创建的头文件应用,接着利用Switch语句来实现选择的功能并在其中插入我们要实现的函数功能,利用指针来访问结构体
然后我们在将所要实现的函数放入头文件中,代码如下
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
CLEAR,
SORT
};
#define DEFAULT_SZ 3
#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 25
//人的信息
typedef struct PeoInfo
{
char name[NAME_MAX];
short age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//通讯录结构体
typedef struct Contact
{
PeoInfo data[MAX];//存放真实数据的空间
int sz;//记录有效数据的个数
}Contact;
void InitContact(Contact* pcon);
void AddContact(Contact* pcon);
void DelContact(Contact* pcon);
void FindContact(Contact* pcon);
void ModifyContact(Contact* pcon);
void ShowContact(const Contact* pcon);
void ClearContact(Contact* pcon);
void SortContact(Contact* pcon);
再次构建结构体是为了方便向通讯录中录入信息。然后我们便来一一实现这些函数
优化部分:我们此处实现的仅仅是可以添加1000个联系人的信息,如果只加三个人的信息,则会浪费空间,如增加的人多,则无法实现,所以我们可以利用动态存储函数来扩容。
首先要修改结构体声明部分:
typedef struct Contact
{
Struct peoInform *data;
int size;
int capacity;//当前通讯录已经有的元素个数
}Contact;
1.初始化结构体信息
void InitContact(Contact* pcon)
{
assert(pcon);
pcon->sz = 0;
memset(pcon->data, 0, sizeof(pcon->data));
}
定义一个函数来初始化通讯录的内容,之后有其他功能进行复制,利用memset函数来实现元素初始化
优化:
在使用动态内存函数后,初始化函数也需要优化:
void InitContact(Contact *pcon)
{
ps->data=(Struct PeoInform*)malloc(Space*sizeof(Struct PeoInform))
if(ps->data=NULL)
{
return;
}
pc->size=0;
ps->capacity = Space;
}
2.增加联系人函数
void AddContact(Contact* pcon)
{
assert(pcon);
if(pcon->sz == pcon->capacity)
{
PeoInfo* tmp=(PeoInfo*)realloc(pcon->data,(pcon->capactity+2)*sizeof(PeoInfo));
if(tmp== NULL)
{
pcon->data=tmp;
}
pc->capacity+=2;
}
//录入信息
printf("请输入名字:>");
scanf("%s", pcon->data[pcon->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pcon->data[pcon->sz].age));
printf("请输入性别:>");
scanf("%s", pcon->data[pcon->sz].sex);
printf("请输入电话:>");
scanf("%s", pcon->data[pcon->sz].tele);
printf("请输入地址:>");
scanf("%s", pcon->data[pcon->sz].addr);
pcon->sz++;
printf("增加成功\n");
}
该函数较为简单,但要注意的是每增加一个联系人信息,便要将sz加1来记录总人数
3.查找人名函数
static int FindByName(Contact* pcon, char name[])
{
int i = 0;
assert(pcon);
for(i=0; i<pcon->sz; i++)
{
if(0 == strcmp(pcon->data[i].name, name))
{
return i;
}
}
//找不到
return -1;
}
为查找名字,要将名字数组传到函数中去,利用strcmp函数比较字符串,通过遍历来查找人名。
3.删除联系人信息函数
void DelContact(Contact* pcon)
{
int i = 0;
char name[NAME_MAX] = {0};
int pos = 0;
assert(pcon);
if(pcon->sz == 0) //空的就不用删了
{
printf("通讯录已空,无法删除\n");
return;
}
//删除
printf("请输入要删除人的名字:>");
scanf("%s", name);
//查找(删除之前需要先查找)
pos = FindByName(pcon, name);
if(pos == -1)
{
printf("要删除的条目不存在\n");
return;
}
//移除
for(i=pos; i<pcon->sz; i++)
{
pcon->data[i] = pcon->data[i+1];
}
pcon->sz--;
printf("删除成功\n");
}
首先要注意要用到前面的查找函数,如果找到此联系人信息用后一个联系人信息覆盖掉,同时将sz减去1重新记录联系人人数
5.修改联系人信息
void ModifyContact(Contact* pcon)
{
int i = 0;
char name[NAME_MAX] = {0};
int pos = 0;
assert(pcon);
if(pcon->sz == 0) //空的就不用找
{
printf("通讯录已空,无法修改信息\n");
return;
}
//修改
printf("请输入要修改条目的姓名:>");
scanf("%s", name);
//查找(修改之前需要先查找)
pos = FindByName(pcon, name);
if(pos == -1)
{
printf("要修改的条目不存在\n");
return;
}
//询问要改什么
printf("请输入要修改什么信息(1-名字,2-年龄,3-性别,4-电话,5-住址):>");
int msg;
scanf("%d", &msg);
switch(msg)
{
case 1:
printf("请输入新的姓名:>");
scanf("%s", pcon->data[pos].name);
break;
case 2:
printf("请输入新的年龄:>");
scanf("%d", &pcon->data[pos].age);
break;
case 3:
printf("请输入新的性别:>");
scanf("%s", pcon->data[pos].sex);
break;
case 4:
printf("请输入新的电话:>");
scanf("%s", pcon->data[pos].tele);
break;
case 5:
printf("请输入新的地址:>");
scanf("%s", pcon->data[pos].addr);
break;
default:
printf("输入有误,修改失败\n");
return;
}
printf("修改成功\n");
}
首先判别通讯录中是否有联系人,其次便将需要修改的联系人的信息重新复制。
6.展示所有联系人信息
void ShowContact(const Contact* pcon)
{
int i = 0;
assert(pcon);
printf("%15s\t%5s\t%5s\t%12s\t%20s\n", "名字", "年龄", "性别", "电话", "地址");
for(i=0; i<pcon->sz; i++)
{
printf("%15s\t%5d\t%5s\t%12s\t%20s\n", pcon->data[i].name,
pcon->data[i].age,
pcon->data[i].sex,
pcon->data[i].tele,
pcon->data[i].addr);
}
}
此函数相较前几种简单,利用遍历即可将所有联系人信息打印出来
7.销毁通讯录
因为我们做出了利用动态内存函数的改进,所以我们应该记得释放开辟的空间防止发生错误
代码如下:
void destorContact(Contact* pcon)
{
free(pc->data);
pc->data = NULL:
pc->capacity=0;
pc->sz=0;
printf("销毁成功");
}
完整函数如下:
contact.h:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
CLEAR,
SORT
};
#define DEFAULT_SZ 3
#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 25
//人的信息
typedef struct PeoInfo
{
char name[NAME_MAX];
short age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//通讯录结构体
typedef struct Contact
{
PeoInfo data[MAX];//存放真实数据的空间
int sz;//记录有效数据的个数
}Contact;
void InitContact(Contact* pcon);
void AddContact(Contact* pcon);
void DelContact(Contact* pcon);
void FindContact(Contact* pcon);
void ModifyContact(Contact* pcon);
void ShowContact(const Contact* pcon);
void ClearContact(Contact* pcon);
void SortContact(Contact* pcon);
contact.c:
#include "Contact.h"
//初始化通讯录
void InitContact(Contact* pcon)
{
assert(pcon);
pcon->sz = 0;
memset(pcon->data, 0, sizeof(pcon->data));
}
//1、添加联系人信息
void AddContact(Contact* pcon)
{
assert(pcon);
//录入信息
printf("请输入名字:>");
scanf("%s", pcon->data[pcon->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pcon->data[pcon->sz].age));
printf("请输入性别:>");
scanf("%s", pcon->data[pcon->sz].sex);
printf("请输入电话:>");
scanf("%s", pcon->data[pcon->sz].tele);
printf("请输入地址:>");
scanf("%s", pcon->data[pcon->sz].addr);
pcon->sz++;
printf("增加成功\n");
}
//查找指定条目下标
static int FindByName(Contact* pcon, char name[])
{
int i = 0;
assert(pcon);
for(i=0; i<pcon->sz; i++)
{
if(0 == strcmp(pcon->data[i].name, name))
{
return i;
}
}
//找不到
return -1;
}
//2、删除指定联系人信息
void DelContact(Contact* pcon)
{
int i = 0;
char name[NAME_MAX] = {0};
int pos = 0;
assert(pcon);
if(pcon->sz == 0) //空的就不用删了
{
printf("通讯录已空,无法删除\n");
return;
}
//删除
printf("请输入要删除人的名字:>");
scanf("%s", name);
//查找(删除之前需要先查找)
pos = FindByName(pcon, name);
if(pos == -1)
{
printf("要删除的条目不存在\n");
return;
}
//移除
for(i=pos; i<pcon->sz; i++)
{
pcon->data[i] = pcon->data[i+1];
}
pcon->sz--;
printf("删除成功\n");
}
//3、查找指定联系人信息
void FindContact(Contact* pcon)
{
int i = 0;
char name[NAME_MAX] = {0};
int pos = 0;
assert(pcon);
if(pcon->sz == 0) //空的就不用删了
{
printf("通讯录已空,无法查找\n");
return;
}
//查找
printf("请输入要查找人的名字:>");
scanf("%s", name);
pos = FindByName(pcon, name);
if(pos == -1)
{
printf("要查找的条目不存在\n");
return;
}
printf("%15s\t%5d\t%5s\t%12s\t%20s\n", pcon->data[pos].name,
pcon->data[pos].age,
pcon->data[pos].sex,
pcon->data[pos].tele,
pcon->data[pos].addr);
}
//4、修改指定联系人信息
void ModifyContact(Contact* pcon)
{
int i = 0;
char name[NAME_MAX] = {0};
int pos = 0;
assert(pcon);
if(pcon->sz == 0) //空的就不用找
{
printf("通讯录已空,无法修改信息\n");
return;
}
//修改
printf("请输入要修改条目的姓名:>");
scanf("%s", name);
//查找(修改之前需要先查找)
pos = FindByName(pcon, name);
if(pos == -1)
{
printf("要修改的条目不存在\n");
return;
}
//询问要改什么
printf("请输入要修改什么信息(1-名字,2-年龄,3-性别,4-电话,5-住址):>");
int msg;
scanf("%d", &msg);
switch(msg)
{
case 1:
printf("请输入新的姓名:>");
scanf("%s", pcon->data[pos].name);
break;
case 2:
printf("请输入新的年龄:>");
scanf("%d", &pcon->data[pos].age);
break;
case 3:
printf("请输入新的性别:>");
scanf("%s", pcon->data[pos].sex);
break;
case 4:
printf("请输入新的电话:>");
scanf("%s", pcon->data[pos].tele);
break;
case 5:
printf("请输入新的地址:>");
scanf("%s", pcon->data[pos].addr);
break;
default:
printf("输入有误,修改失败\n");
return;
}
printf("修改成功\n");
}
//5、显示所有联系人信息
void ShowContact(const Contact* pcon)
{
int i = 0;
assert(pcon);
printf("%15s\t%5s\t%5s\t%12s\t%20s\n", "名字", "年龄", "性别", "电话", "地址");
for(i=0; i<pcon->sz; i++)
{
printf("%15s\t%5d\t%5s\t%12s\t%20s\n", pcon->data[i].name,
pcon->data[i].age,
pcon->data[i].sex,
pcon->data[i].tele,
pcon->data[i].addr);
}
}
//6、清空所有联系人信息
void ClearContact(Contact* pcon)
{
InitContact(pcon);
}
//7、按照名字排序
void SortContact(Contact* pcon)
{
int i, j;
PeoInfo tmp;
for(i = 0; i < pcon->sz - 1; i++)
{
for(j = 0; j < pcon->sz - 1 - i; j++)
{
if(0 < strcmp(pcon->data[j].name, pcon->data[j + 1].name))
{
tmp = pcon->data[j];
pcon->data[j] = pcon->data[j + 1];
pcon->data[j + 1] = tmp;
}
}
}
}
测试代码:
#include "Contact.h"
void menu()
{
printf("******************************\n");
printf("** 1. add 2. del **\n");
printf("** 3. search 4. modify **\n");
printf("** 5. show 6. clear **\n");
printf("** 7. sort 0. exit **\n");
printf("******************************\n");
}
int main()
{
int input = 0;
//创建通讯录
Contact con;//
//初始化通讯录
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch(input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case SEARCH:
FindContact(&con);
break;
case SORT:
SortContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case SHOW:
ShowContact(&con);
break;
case CLEAR:
ClearContact(&con);
break;
case EXIT:
printf("退出程序\n");
return 0;
default:
printf("输入有误,请重新输入\n");
break;
}
} while (input);
return 0;
}