目录
一、程序的总线
首先我们需要建立两个头文件'utili.h'、'Contact.h',头文件'utili.h'作为公共头文件主要去引用在程序中调用的库函数的头文件,头文件'Contact'进行自定义函数的声明;以及两个源文件'Contact.c'、'ContactMain.c',源文件'Contact.c'主要进行通讯录各个函数功能的实现,源文件'ContactMain.c'作为驱动文件进行程序运行。
二、通讯录的简单介绍
接下来对本次实现的通讯录进行一个简单的介绍,通讯录中个人信息包括姓名、性别、年龄、电话、住址。通讯录共有七个功能,添加、删除、清除、查找、修改、排序、显示,本程序都是通过姓名来实现查找、排序等功能,当然我们也可以通过年龄、性别等实现。通讯录目录如下(输入相应的数字执行对应的功能):
- 目录如下:
int main()
{
int select = 1;
while (select)
{
printf("******************************\n");
printf("**********通 讯 录************\n");
printf("*[1]Add [2]Del *\n");
printf("*[3]Clear [4]Find *\n");
printf("*[5]Modify [6]Sort *\n");
printf("*[0]Exit [7]Show *\n");
printf("******************************\n");
printf("请选择:>");
scanf("%d", &select);
}
return 0;
}
- 显示如下:
三、各个构造函数介绍
这部分是对各个分部函数的介绍,如果有些地方看不懂,可以去后面看一下总体的代码,再回来看这部分。该通讯录默认通过姓名进行查询、排序等。
两个结构体,一个个人信息的结构体,一个通讯录的结构体,方便下面代码的阅读。
//定义信息结构
typedef struct PersonInfo
{
char name[MAX_NAME_SIZE];
char sex[MAX_SEX_SIZE];
int age;
char tele[MAX_TELE_SIZE];
char address[MAX_ADDRESS_SIZE];
}PersonInfo;
//定义通讯录结构
typedef struct Contact
{
PersonInfo cont[MAX_CONTACT_SIZE];
size_t capacity;//通讯录总容量
size_t size;//通讯录当前成员个数
}Contact;
1、初始化函数
在对于通讯录进行一系列操作之前,我们有时候会需要对通讯录进行初始化,需要用到内存函数memset,此时需要在公共头文件中引用头文件<string.h>,代码如下:
void InitContact(Contact *pcnt)//对通讯录进行初始化
{
memset(pcnt->cont, 0, sizeof(PersonInfo)*MAX_CONTACT_SIZE);
pcnt->capacity = MAX_CONTACT_SIZE;
pcnt->size = 0;
}
2、容量检查函数
在进行添加操作前,我们需要对通讯录进行判断是否有空间可以添加,此时需要用到检查通讯录容量的函数,其返回值为bool类型,则需要在公共头文件中引用头文件<stdbool.h>,函数实现如下:
bool IsFull(Contact *pcnt)//检查容量
{
return pcnt->size >= pcnt->capacity;
}
3、通讯录查询函数
查找时,需要用到字符串比较函数strcmp,如果找到返回下表,没找到返回-1.
int FindByName(Contact *pcnt,char* name)//通过姓名查找
{
for (int i = 0; i < pcnt->size; ++i)
{
if (strcmp(name, pcnt->cont[i].name) == 0)
return i;
}
return -1;
}
4、打印函数
对通讯录信息进行打印时,我们需要考虑一个问题,我们需要打印姓名、性别、电话等信息,那么我们如何能够确保打印出来比较规整,就是信息之间的对齐问题,这个需要重视一下。代码如下·(两个printf在打印时处理了格式的问题):
void ShowContact(Contact *pcnt)
{
printf("%-8s%-6s%-6s%-13s%s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < pcnt->size; ++i)
{
printf("%-8s%-6s%-6d%-13s%s\n", pcnt->cont[i].name,
pcnt->cont[i].sex,
pcnt->cont[i].age,
pcnt->cont[i].tele,
pcnt->cont[i].address);
}
}
5、通讯录添加函数
在进行通讯录添加时,我们需要先对通讯录的空间进行判断,如果通讯录已满,则无法再进行添加,如果可以添加,依次输入添加信息即可。代码如下:
void AddContact(Contact *pcnt)
{
//检查容量
if (IsFull(pcnt))
{
printf("通讯录已满,无法进行添加!!!\n");
return;
}
printf("姓名:>");
scanf("%s", pcnt->cont[pcnt->size].name);
printf("性别:>");
scanf("%s", pcnt->cont[pcnt->size].sex);
printf("年龄:>");
scanf("%d", &pcnt->cont[pcnt->size].age);
printf("电话:>");
scanf("%s", pcnt->cont[pcnt->size].tele);
printf("地址:>");
scanf("%s", pcnt->cont[pcnt->size].address);
pcnt->size++;
printf("信息添加成功\n");
}
6、通讯录成员删除函数
在进行通讯录成员删除时,找到成员下标,只需要让后面的成员整体向前覆盖就行,在向前覆盖的时候,我们可以直接结构体给结构体赋值,这样可以节省我们大量的时间,同时,覆盖完成后,通讯录成员个数减一即可。代码如下:
void DelContact(Contact *pcnt)//通讯录成员删除
{
char name[MAX_NAME_SIZE];
printf("请输入要删除的成员的姓名:");
scanf("%s", name);
int index = FindByName(pcnt, name);
if (index == -1)
{
printf("信息不存在!!!\n");
return;
}
for (int i = index; i < pcnt->size-1; ++i)
{
pcnt->cont[i] = pcnt->cont[i + 1];//结构体给结构体赋值
}
pcnt->size--;
}
7、通讯录清除函数
清空通讯录时,我们只需要将通讯录成员个数size置零即可,不需要对成员进行初始化,这么做还有一个好处就是如果我们清除后想要恢复,那是不是再给size赋值便可以了呢?代码如下:
void ClearContact(Contact *pcnt)//通讯录清空
{
printf("是否清空通讯录<Y/N>?\n");
fflush(stdin);//清除上一次的换行符
char ch = getchar();
if (ch == 'N')
{
printf("未清空通讯录!\n");
return;
}
else if (ch == 'Y')
{
pcnt->size = 0;
printf("清空通讯录成功!\n");
}
else
printf("输入错误!!!\n");
}
8、通讯录查找函数
查找时,首先我们需要判断通讯录是否为空,如果为空,则无法查找;不为空则需要找到查找信息的下标,对该行信息进行打印,代码如下:
void FindContact(Contact *pcnt)//通讯录查找函数
{
if (IsEmpty(pcnt))
{
printf("通讯录为空,不能查找!!!\n");;
return;
}
char name[MAX_NAME_SIZE];
printf("请输入查询的姓名:");
scanf("%s", name);
int index = FindByName(pcnt,name);
if (index == -1)
{
printf("信息不存在!!!\n");
return;
}
printf("%-8s%-6s%-6d%-13s%s\n", pcnt->cont[index].name,
pcnt->cont[index].sex,
pcnt->cont[index].age,
pcnt->cont[index].tele,
pcnt->cont[index].address);
}
9、通讯录成员信息修改函数
在进行成员信息修改时,我们需要判断通讯录是否为空,然后找到需要修改信息成员的下标,输入其需要修改的信息进行修改。代码如下:
void ModifyContact(Contact *pcnt)//通讯录成员信息修改
{
if (IsEmpty(pcnt))
{
printf("通讯录为空,不能修改!!!\n");
return;
}
char name[MAX_NAME_SIZE];
printf("请输入要修改成员的姓名:");
scanf("%s", name);
int index = FindByName(pcnt, name);
if (index == -1)
{
printf("修改的成员不存在!!!\n");
return;
}
printf("想要修改什么信息(1-姓名,2-性别,3-年龄,4-电话,5-地址)\n");
int select;
scanf("%d", &select);
switch (select)//switch来进行修改信息的选择
{
case 1:
printf("请输入要修改的姓名:");
scanf("%s", pcnt->cont[index].name);
break;
case 2:
printf("请输入要修改的性别:");
scanf("%s", pcnt->cont[index].sex);
break;
case 3:
printf("请输入要修改的年龄:");
scanf("%d", &pcnt->cont[index].age);
break;
case 4:
printf("请输入要修改的电话:");
scanf("%s", pcnt->cont[index].tele);
break;
case 5:
printf("请输入要修改的地址:");
scanf("%s", pcnt->cont[index].address);
break;
}
}
10、通讯录排序函数
这里我们可以通过冒泡排序来实现,对于姓名的排序,通过姓名拼字字符串比大小来确定成员的先后顺序。
void SortContact(Contact *pcnt)//通讯录排序
{
for (int i = 0; i < pcnt->size - 1; ++i)
{
for (int j = 0; j < pcnt->size - i - 1; ++j)
{
if (strcmp(pcnt->cont[j].name, pcnt->cont[j + 1].name)>0)
{
PersonInfo tmp = pcnt->cont[j];
pcnt->cont[j] = pcnt->cont[j + 1];
pcnt->cont[j + 1] = tmp;
}
}
}
printf("排序成功!\n");
}
四、程序代码
1、头文件'utili.h'
用来存放该程序用到的库函数的头文件。
#ifndef _UTILI_H_
#define _UTILI_H_
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#endif/*_UTILI_H_*/
2、头文件'Contact.h'
用来存放程序自定义函数的声明、自定义的结构体、定义的宏以及枚举变量
#ifndef _CONTACT_H_
#define _CONTACT_H_
#include"utili.h"
enum{
Exit,Add,Del,Clear,Find,Modify,Sort,Show//注意顺序与功能相对应
};
#define MAX_NAME_SIZE 20
#define MAX_SEX_SIZE 3
#define MAX_TELE_SIZE 12
#define MAX_ADDRESS_SIZE 256
#define MAX_CONTACT_SIZE 1000
//定义信息结构
typedef struct PersonInfo
{
char name[MAX_NAME_SIZE];
char sex[MAX_SEX_SIZE];
int age;
char tele[MAX_TELE_SIZE];
char address[MAX_ADDRESS_SIZE];
}PersonInfo;
//定义通讯录结构
typedef struct Contact
{
PersonInfo cont[MAX_CONTACT_SIZE];
size_t capacity;
size_t size;
}Contact;
//函数的声明
bool IsFull(Contact *pcnt);//检查通讯录容量
bool IsEmpty(Contact *pcnt);//判断通讯录是否为空
int FindByName(Contact *pcnt,char);//通过姓名查找,返回其下标
void InitContact(Contact *pcnt);//对通讯录进行初始化
void AddContact(Contact *pcnt);//对通讯录进行成员添加
void DelContact(Contact *pcnt);//通讯录成员删除
void clearContact(Contact *pcnt);//通讯录信息清空
void FindContact(Contact *pcnt);//通讯录查找
void ModifyContact(Contact *pcnt);//通讯录成员信息修改
void SortContact(Contact *pcnt);//通讯录排序
void ShowContact(Contact *pcnt);//对通讯录进行打印
#endif /*_CONTACT_H_*/
3、源文件'Contact.c'
用来存放程序中用到的所有自定义函数的主体,所有自定义函数的实现均在其中。
#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
void InitContact(Contact *pcnt)//对通讯录进行初始化
{
memset(pcnt->cont, 0, sizeof(PersonInfo)*MAX_CONTACT_SIZE);
pcnt->capacity = MAX_CONTACT_SIZE;
pcnt->size = 0;
}
bool IsFull(Contact *pcnt)//检查容量
{
return pcnt->size >= pcnt->capacity;
}
bool IsEmpty(Contact *pcnt)//判断通讯录是否为空
{
return pcnt->size == 0;
}
int FindByName(Contact *pcnt,char* name)//通过姓名查找
{
for (int i = 0; i < pcnt->size; ++i)
{
if (strcmp(name, pcnt->cont[i].name) == 0)
return i;
}
return -1;
}
void AddContact(Contact *pcnt)//添加信息
{
//检查容量
if (IsFull(pcnt))
{
printf("通讯录已满,无法进行添加!!!\n");
return;
}
printf("姓名:");
scanf("%s", pcnt->cont[pcnt->size].name);
printf("性别:");
scanf("%s", pcnt->cont[pcnt->size].sex);
printf("年龄:");
scanf("%d", &pcnt->cont[pcnt->size].age);
printf("电话:");
scanf("%s", pcnt->cont[pcnt->size].tele);
printf("地址:");
scanf("%s", pcnt->cont[pcnt->size].address);
pcnt->size++;
printf("信息添加成功\n");
}
void DelContact(Contact *pcnt)//通讯录成员删除
{
char name[MAX_NAME_SIZE];
printf("请输入要删除的成员的姓名:");
scanf("%s", name);
int index = FindByName(pcnt, name);
if (index == -1)
{
printf("信息不存在!!!\n");
return;
}
for (int i = index; i < pcnt->size-1; ++i)
{
pcnt->cont[i] = pcnt->cont[i + 1];
}
pcnt->size--;
printf("删除信息成功!!!\n");
}
void ClearContact(Contact *pcnt)//通讯录清空
{
printf("是否清空通讯录<Y/N>?\n");
fflush(stdin);//清除上一次的换行符
char ch = getchar();
if (ch == 'N')
{
printf("未清空通讯录!\n");
return;
}
else if (ch == 'Y')
{
pcnt->size = 0;
printf("清空通讯录成功!\n");
}
else
printf("输入错误!!!\n");
}
void FindContact(Contact *pcnt)//通讯录查找函数
{
if (IsEmpty(pcnt))
{
printf("通讯录为空,不能查找!!!\n");;
return;
}
char name[MAX_NAME_SIZE];
printf("请输入查询的姓名:");
scanf("%s", name);
int index = FindByName(pcnt,name);
if (index == -1)
{
printf("信息不存在!!!\n");
return;
}
printf("%-8s%-6s%-6d%-13s%s\n", pcnt->cont[index].name,
pcnt->cont[index].sex,
pcnt->cont[index].age,
pcnt->cont[index].tele,
pcnt->cont[index].address);
}
void ModifyContact(Contact *pcnt)//通讯录成员信息修改
{
if (IsEmpty(pcnt))
{
printf("通讯录为空,不能修改!!!\n");
return;
}
char name[MAX_NAME_SIZE];
printf("请输入要修改成员的姓名:");
scanf("%s", name);
int index = FindByName(pcnt, name);
if (index == -1)
{
printf("修改的成员不存在!!!\n");
return;
}
printf("想要修改什么信息(1-姓名,2-性别,3-年龄,4-电话,5-地址)\n");
int select;
scanf("%d", &select);
switch (select)
{
case 1:
printf("请输入要修改的姓名:");
scanf("%s", pcnt->cont[index].name);
break;
case 2:
printf("请输入要修改的性别:");
scanf("%s", pcnt->cont[index].sex);
break;
case 3:
printf("请输入要修改的年龄:");
scanf("%d", &pcnt->cont[index].age);
break;
case 4:
printf("请输入要修改的电话:");
scanf("%s", pcnt->cont[index].tele);
break;
case 5:
printf("请输入要修改的地址:");
scanf("%s", pcnt->cont[index].address);
break;
}
}
void SortContact(Contact *pcnt)//通讯录排序
{
for (int i = 0; i < pcnt->size - 1; ++i)
{
for (int j = 0; j < pcnt->size - i - 1; ++j)
{
if (strcmp(pcnt->cont[j].name, pcnt->cont[j + 1].name)>0)
{
PersonInfo tmp = pcnt->cont[j];
pcnt->cont[j] = pcnt->cont[j + 1];
pcnt->cont[j + 1] = tmp;
}
}
}
printf("排序成功!\n");
}
void ShowContact(Contact *pcnt)//打印通讯录
{
printf("%-8s%-6s%-6s%-13s%s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < pcnt->size; ++i)
{
printf("%-8s%-6s%-6d%-13s%s\n", pcnt->cont[i].name,
pcnt->cont[i].sex,
pcnt->cont[i].age,
pcnt->cont[i].tele,
pcnt->cont[i].address);
}
}
4、源文件'ContactMain.c'
程序的主函数,实现目录的打印,以及自定义函数的调用,通过switch语句实现通讯录功能的选择。
#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
int main(int argc,char* argv[])
{
//初始化通讯录
Contact cont;
InitContact(&cont);
int select = 1;
while (select)
{
printf("******************************\n");
printf("**********通 讯 录************\n");
printf("*[1]Add [2]Del *\n");
printf("*[3]Clear [4]Find *\n");
printf("*[5]Modify [6]Sort *\n");
printf("*[0]Exit [7]Show *\n");
printf("******************************\n");
printf("请选择:>");
scanf("%d", &select);
if (select == 0)
break;
switch (select)
{
case(Add):
AddContact(&cont);
break;
case(Del) :
DelContact(&cont);
break;
case(Clear) :
ClearContact(&cont);
break;
case(Find) :
FindContact(&cont);
break;
case(Modify) :
ModifyContact(&cont);
break;
case(Sort) :
SortContact(&cont);
break;
case(Show) :
ShowContact(&cont);
break;
}
}
printf("退出通讯录系统…………\n");
return 0;
}