博客主页:️自信不孤单
文章专栏:C语言
代码仓库:破浪晓梦
欢迎关注:欢迎大家点赞收藏+关注
在实现通讯录前,我们需先考虑要实现的通讯录应该具备哪些功能,以下是我写的通讯录功能预览:
- 添加联系人信息
- 删除指定联系人信息
- 查找指定联系人信息
- 修改指定联系人信息
- 显示所有联系人信息
- 清空所有联系人
- 排序通讯录联系人
我们通过三个文件来实现上述通讯录:
- test.c——整个通讯录的逻辑实现
- contact.h——通讯录相关功能的函数声明
- contact.c——通讯录相关功能的函数实现
- 先创建一个用户选择菜单
static void menu()
{
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");
}
- 定义枚举类型定义常量,方便调用switch语句时使用
enum Optition
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
- 在main函数内部实现通讯录的基本框架(这里的Contact自定义类型已在contact.h文件里面声明了)
int main()
{
int input = 0;
Contact con;
//初始化通讯录
InitContact(&con);
do
{
menu();
printf("请输入操作选项:>");
scanf("%d", &input);
switch (input)
{
case ADD:
Add(&con);
break;
case DEL:
Del(&con);
break;
case SEARCH:
Search(&con);
break;
case MODIFY:
Modify(&con);
break;
case SHOW:
Show(&con);
break;
case SORT:
Sort(&con);
break;
case EXIT:
printf("退出通讯录\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
在创建的头文件里把需要的头文件加上,这样其他两个.c文件只需要声明我们自己创建的头文件就可以使用库函数了。
用#define定义常量表示数据的最大容量,方便修改。
创建一个结构体来描述一个联系人的信息。
创建一个结构体,存放1000个联系人的信息,再创建一个整型变量,用来记录当前存放有效信息的个数。
#include
#include
#include
#define MAX 1000
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 40
//描述一个人的信息
typedef struct PeopleInfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeopleInfo;
//通讯录
typedef struct Contact
{
PeopleInfo data[MAX];//定义数组用来存放联系人信息
int sz;//记录通讯录中有效信息的个数
}Contact;
对功能函数的声明
//初始化通讯录
void InitContact(Contact* pc);
//添加联系人信息
void Add(Contact* pc);
//删除联系人信息
void Del(Contact* pc);
//显示联系人信息
void Show(Contact* pc);
//查找联系人信息
void Search(const Contact* pc);
//修改联系人信息
void Modify(Contact* pc);
//按名字排序通讯录
void Sort(Contact* pc);
在创建好数组后其实里面的数值都是些随机数,我们需要将记录有效信息个数的sz置为0,然后把数组的元素全部置0,这里使用memset函数。
void InitContact(Contact* pc)
{
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
增加联系人之前我们需要判断通讯录是否满了,如果满了就提示无法添加。没满就开始添加数据,记录联系人个数的变量sz刚好可以对应添加数组的下标,每次添加sz+1。
void Add(Contact* pc)
{
if (pc->sz == MAX)
{
printf("通讯录已满,无法继续填入信息\n");
return;
}
printf("请输入姓名:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入电话号:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入住址:>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
添加联系人后我们想知道是否添加成功了,这时就可以实现显示联系人功能的函数来测试是否添加成功。显示通讯录只需要遍历一遍数组打印出来就行了。
void Show(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
printf("%-20s%-10s%-20s%-20s%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < pc->sz; i++)
{
printf("%-20s%-10s%-20d%-20s%-30s\n",
pc->data[i].name, pc->data[i].sex,
pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
}
}
在删除联系人之前我们要先找那个联系人才能删除,如果找不到则无法删除。因为想到之后也要使用此功能,所以干脆封装成一个查找的函数,如果找到了就返回下标,如果找不到就返回-1。
//查找联系人姓名
static int Find(const Contact* pc, const char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(name, pc->data[i].name) == 0)
{
return i;
}
}
return -1;
}
然后实现删除联系人函数
void Del(Contact* pc)
{
char name[MAX_NAME] = {0};
int ret = 0, i = 0;
printf("请输入要删除人的姓名:>");
scanf("%s", name);
ret = Find(pc, name);
if (ret == -1)
{
printf("删除失败,该联系人不存在\n");
return;
}
else
{
for (i = ret; i < pc->sz-1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
}
查找联系人,可以使用上面写的查找函数,找到就打印出来,没找到就输出被查找人不存在。
void Search(const Contact* pc)
{
char name[MAX_NAME] = { 0 };
int ret = 0;
printf("请输入要查找人的名字:>");
scanf("%s", name);
ret = Find(pc, name);
if (ret == -1)
{
printf("该联系人不存在\n");
return;
}
else
{
printf("%-20s%-10s%-20s%-20s%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-20s%-10s%-20d%-20s%-30s\n", pc->data[ret].name, pc->data[ret].sex,
pc->data[ret].age, pc->data[ret].tele, pc->data[ret].addr);
}
}
修改联系人也用到了查找函数,找到了就进行修改,找不到就输出该联系人不存在。
void Modify(Contact* pc)
{
char name[MAX_NAME] = { 0 };
int ret = 0;
printf("请输入要修改人的姓名:>");
scanf("%s", name);
ret = Find(pc, name);
if (ret == -1)
{
printf("该联系人不存在\n");
return;
}
else
{
printf("请输入姓名:>");
scanf("%s", pc->data[ret].name);
printf("请输入性别:>");
scanf("%s", pc->data[ret].sex);
printf("请输入年龄:>");
scanf("%d", &(pc->data[ret].age));
printf("请输入电话号:>");
scanf("%s", pc->data[ret].tele);
printf("请输入住址:>");
scanf("%s", pc->data[ret].addr);
printf("修改成功\n");
}
}
排序联系人可以使用qsort函数实现。(这里我们对名字进行排序)
int compare_name(const void* p1, const void* p2)
{
return strcmp(((PeopleInfo*)p1)->name, ((PeopleInfo*)p2)->name);
}
void Sort(Contact* pc)
{
qsort(pc->data, pc->sz, sizeof(PeopleInfo), compare_name);
printf("排序成功\n");
}
tect.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
enum Optition
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
static void menu()
{
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");
}
int main()
{
int input = 0;
Contact con;
//初始化通讯录
InitContact(&con);
do
{
menu();
printf("请输入操作选项:>");
scanf("%d", &input);
switch (input)
{
case ADD:
Add(&con);
break;
case DEL:
Del(&con);
break;
case SEARCH:
Search(&con);
break;
case MODIFY:
Modify(&con);
break;
case SHOW:
Show(&con);
break;
case SORT:
Sort(&con);
break;
case EXIT:
printf("退出通讯录\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
contact.h文件
#pragma once
#include
#include
#include
#define MAX 1000
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 40
//描述一个人的信息
typedef struct PeopleInfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeopleInfo;
//通讯录
typedef struct Contact
{
PeopleInfo data[MAX];//定义数组用来存放联系人信息
int sz;//记录通讯录中有效信息的个数
}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//添加联系人信息
void Add(Contact* pc);
//删除联系人信息
void Del(Contact* pc);
//显示联系人信息
void Show(Contact* pc);
//查找联系人信息
void Search(const Contact* pc);
//修改联系人信息
void Modify(Contact* pc);
//按名字排序通讯录
void Sort(Contact* pc);
contact.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void InitContact(Contact* pc)
{
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
void Add(Contact* pc)
{
if (pc->sz == MAX)
{
printf("通讯录已满,无法继续填入信息\n");
return;
}
printf("请输入姓名:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入电话号:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入住址:>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
void Show(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
printf("%-20s%-10s%-20s%-20s%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < pc->sz; i++)
{
printf("%-20s%-10s%-20d%-20s%-30s\n",
pc->data[i].name, pc->data[i].sex,
pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
}
}
//查找联系人姓名
static int Find(const Contact* pc, const char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(name, pc->data[i].name) == 0)
{
return i;
}
}
return -1;
}
void Del(Contact* pc)
{
char name[MAX_NAME] = {0};
int ret = 0, i = 0;
printf("请输入要删除人的姓名:>");
scanf("%s", name);
ret = Find(pc, name);
if (ret == -1)
{
printf("删除失败,该联系人不存在\n");
return;
}
else
{
for (i = ret; i < pc->sz-1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
}
void Search(const Contact* pc)
{
char name[MAX_NAME] = { 0 };
int ret = 0;
printf("请输入要查找人的名字:>");
scanf("%s", name);
ret = Find(pc, name);
if (ret == -1)
{
printf("该联系人不存在\n");
return;
}
else
{
printf("%-20s%-10s%-20s%-20s%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-20s%-10s%-20d%-20s%-30s\n", pc->data[ret].name, pc->data[ret].sex,
pc->data[ret].age, pc->data[ret].tele, pc->data[ret].addr);
}
}
void Modify(Contact* pc)
{
char name[MAX_NAME] = { 0 };
int ret = 0;
printf("请输入要修改人的姓名:>");
scanf("%s", name);
ret = Find(pc, name);
if (ret == -1)
{
printf("该联系人不存在\n");
return;
}
else
{
printf("请输入姓名:>");
scanf("%s", pc->data[ret].name);
printf("请输入性别:>");
scanf("%s", pc->data[ret].sex);
printf("请输入年龄:>");
scanf("%d", &(pc->data[ret].age));
printf("请输入电话号:>");
scanf("%s", pc->data[ret].tele);
printf("请输入住址:>");
scanf("%s", pc->data[ret].addr);
printf("修改成功\n");
}
}
int compare_name(const void* p1, const void* p2)
{
return strcmp(((PeopleInfo*)p1)->name, ((PeopleInfo*)p2)->name);
}
void Sort(Contact* pc)
{
qsort(pc->data, pc->sz, sizeof(PeopleInfo), compare_name);
printf("排序成功\n");
}
静态版通讯录的空间是一开始就给定的,如果空间满了又不能增加空间,而如果使用的空间并没有那么大则又造成了浪费空间。这些问题的解决方案请观看我后续的文章《通讯录——动态版》!
到此,关于《通讯录——静态版》的内容就结束了
感谢大家的观看
创作不易,如果对您有帮助,请一键三连
您的支持就是我创作最大的动力!!!