通讯录,每个人手机上都有的软件,可以用来存储联系人的姓名,年龄,号码,家庭住址等等,那么学了这么长时间c语言的你一定很好奇通信录怎么用c语言学出来吧,此文章就详细讲解通讯录思路以及代码实现,创作不易,还请各位小伙伴多多关注点赞收藏⭐,以后也会更新各种小项目和C/C++相关的知识。✨✨
- 这种涉及到几个文件的项目通常可以锻炼到我们模块化编程的思维,啥是模块化编程呢?
模块化编程:模块化编程就是把我们的一整个项目,分成很多模块(比如我们生产汽车,可以分为生产发动机、生产轮胎、生产车架、组装等)而一个程序工程包含多个源文件(.c 文件和 .h 文件),每个 .c 文件可以被称为一个模块,每一个模块都有其各自的功能,而每一个.h文件则是声明该模块,相当于功能说明书 ,大大提高代码可阅读性,不会使代码显得臃肿。
以下图为模板通讯录进行还原,其中包含序号、姓名、年龄、性别、联系电话、家庭住址,并且为其添加最基本的增删改查以及排序等功能。
1.添加联系人
2.删除联系人
3.搜索联系人
4.修改联系人
5.显示通讯录
6.排序通讯录(这里选择用年龄排序)
0.退出通讯录
- 每次完成操作后重新回到主菜单页面,直到输入0退出,所以程序主体我们可以选择一个循环来进行,菜单选择采用switch case语句
- 进入程序,首先出现在我们眼前的是菜单,所有首先我们要打印一个菜单
- 第一个选项是增加联系人操作,联系人信息包括姓名、年龄、性别、联系电话、家庭住址,我们可以将这一组信息打包进一个结构体里。
- 第二个选项是删除联系人,输入联系人的姓名对其进行删除。
- 第三个选项是搜索联系人,输入联系人的姓名,输出此联系人的信息。
- 第四个选项是修改,输入要修改联系人的姓名,对其进行修改
- 第五个选项是显示联系人列表,将通讯录内所有信息打印
- 第六个选项是排序通讯录,作者选择用年龄进行排序。
- 第七个选项是清空通讯录,清空通讯录
- 最后一个选项是退出程序,这里选择用0的原因是可以用这个0来作为程序循环的结束条件,退出后将通讯录信息保存到文件内,使得下次打开程序里面的联系人都还在。(每次进入程序先加载文件信息)。
void menu()
{
printf("********************************\n");
printf("***** 1.Add 2.Del *****\n");
printf("***** 3.Search 4.Modif *****\n");
printf("***** 5.Show 6.Sort *****\n");
printf("***** 7.clear 0.Exit *****\n");
printf("********************************\n");
}
菜单是程序不可或缺的一部分,让使用者知道怎么操作。
enum option
{
Exit,
Add,
Del,
Search,
Modify,
Show,
Sort,
Clear
};
int main()
{
int input = 0;
Contact con; //创建一个通讯录
InitContact(&con);
do
{
menu();
printf("请选择要进行的操作\n");
scanf("%d", &input);
switch (input)
{
case Add:
AddContact(&con); //添加联系人
break;
case Del:
DelContact(&con); //删除联系人
break;
case Search:
SearchContact(&con); //搜索联系人
break;
case Modify:
ModifyContact(&con); //修改联系人
break;
case Show:
ShowContact(&con); //展示通讯录
break;
case Sort:
SortContact(&con); //排序通讯录
break;
case Clear:
ClearContact(&con); //清理通讯录
break;
case Exit:
SaveContact(&con); //保存通讯录
ExitContact(&con); //退出通讯录
printf("退出成功\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
进入程序,直接一张菜单弹出所以这里选择do。while语句,再用switch语句进行判断,当用户选择对应的选项执行对应的函数。
一个联系人的信息包括姓名、年龄、性别、联系电话、家庭住址,最适合装载此信息的变量肯定就是结构体了。
这里使用一些宏定义的原因是方便修改,如果以后通讯录想修改某字符串的或某重要变量的长度可以很快速的找到,并且只修改这一个地方即可。
#define MAX_NAME 20 //姓名长度
#define MAX_SEX 5 //性别长度
#define MAX_NUMBER 15 //电话号码长度
#define MAX_ADDRESS 20 //家庭住址长度
#define DEFAULT_SZ 3 //动态内存管理用到的默认通讯录的联系人个数
//通讯录数量为什么不设置成固定的值❔一是节省空间,二是固定的如果装满了需要改写太麻烦。
#define DEFAULT_INC 2
//动态内存管理用到变量,通讯录每次装满之后自增的个数。
typedef struct PeoInfo //联系人
{
char name[MAX_NAME]; //姓名
int age; //年龄
char sex[MAX_SEX]; //性别
char number[MAX_NUMBER]; //电话号码
char address[MAX_ADDRESS]; //地址
}PeoInfo;
typedef struct Contact
{
PeoInfo* data; //用动态内存方式存储信息,所有定义成指针而不是数组,指向联系人。
int sz; //当前联系人个数
int Capable; //当前能装载的最大联系人个数
}Contact;
//静态版本
//typedef struct Contact
//{
// PeoInfo data[100];
// int sz;
//}Contact;
//初始化通讯录
void InitContact(Contact* c)
{
PeoInfo* ptr = (PeoInfo*)malloc(sizeof(PeoInfo) * DEFAULT_SZ);
if (ptr == NULL)
{
printf("%s", strerror(errno));
return;
}
c->sz = 0; //将当前联系人个数初始化为0
c->Capable = DEFAULT_SZ; //当前最大联系人个数初始化为DEFAULT_SZ
c->data = ptr;
LoadingContact(c); //加载保存到文件夹的联系人信息
}
//静态版本
//void InitContact(Contact *c)
//{
// c->sz = 0;
// memset(c->data, 0, sizeof(c->data));
//}
void CheckContact(Contact* c)
{
if (c->sz == c->Capable) //如果当前联系人数量等于当前联系人最大数量,最大数量+DEFAULT_INC
{
PeoInfo* ptr = (PeoInfo*)realloc(c->data, (DEFAULT_INC + c->Capable) * sizeof(PeoInfo));
if (ptr == NULL) //如果没申请到空间,报错返回
{
printf("%s", strerror(errno));
return;
}
c->Capable = c->Capable + DEFAULT_INC; //把当前联系人最大数量+DEFAULT_INC
c->data = ptr;
printf("扩容成功\n");
}
}
void AddContact(Contact* c)
{
CheckContact(c); //检查当前空间是否足够
printf("请输入要添加的联系人\n");
printf("请输入姓名\n");
scanf("%s", c->data[c->sz].name);
printf("请输入年龄\n");
scanf("%d", &(c->data[c->sz].age));
printf("请输入性别\n");
scanf("%s", c->data[c->sz].sex);
printf("请输入号码\n");
scanf("%s", c->data[c->sz].number);
printf("请输入地址\n");
scanf("%s", c->data[c->sz].address);
c->sz++;
}
//静态版
//void AddContact(Contact* c)
//{
// if (c->sz== 100)
// {
// printf("人数已满,不能继续添加\n");
// return;
// }
// printf("请输入要添加的联系人\n");
// printf("请输入姓名\n");
// scanf("%s", c->data[c->sz].name);
// printf("请输入年龄\n");
// scanf("%d", &(c->data[c->sz].age));
// printf("请输入性别\n");
// scanf("%s", c->data[c->sz].sex);
// printf("请输入号码\n");
// scanf("%s", c->data[c->sz].number);
// printf("请输入地址\n");
// scanf("%s", c->data[c->sz].address);
// c->sz++;
//}
void CheckContact(Contact* c)
{
if (c->sz == c->Capable) //如果当前联系人数量等于当前联系人最大数量,最大数量+DEFAULT_INC
{
PeoInfo* ptr = (PeoInfo*)realloc(c->data, (DEFAULT_INC + c->Capable) * sizeof(PeoInfo));
if (ptr == NULL) //如果没申请到空间,报错返回
{
printf("%s", strerror(errno));
return;
}
c->Capable = c->Capable + DEFAULT_INC; //把当前联系人最大数量+DEFAULT_INC
c->data = ptr;
printf("扩容成功\n");
}
}
void AddContact(Contact* c)
{
CheckContact(c); //检查当前空间是否足够
printf("请输入要添加的联系人\n");
printf("请输入姓名\n");
scanf("%s", c->data[c->sz].name);
printf("请输入年龄\n");
scanf("%d", &(c->data[c->sz].age));
printf("请输入性别\n");
scanf("%s", c->data[c->sz].sex);
printf("请输入号码\n");
scanf("%s", c->data[c->sz].number);
printf("请输入地址\n");
scanf("%s", c->data[c->sz].address);
c->sz++;
}
//静态版
//void AddContact(Contact* c)
//{
// if (c->sz== 100)
// {
// printf("人数已满,不能继续添加\n");
// return;
// }
// printf("请输入要添加的联系人\n");
// printf("请输入姓名\n");
// scanf("%s", c->data[c->sz].name);
// printf("请输入年龄\n");
// scanf("%d", &(c->data[c->sz].age));
// printf("请输入性别\n");
// scanf("%s", c->data[c->sz].sex);
// printf("请输入号码\n");
// scanf("%s", c->data[c->sz].number);
// printf("请输入地址\n");
// scanf("%s", c->data[c->sz].address);
// c->sz++;
//}
void DelContact(Contact* c)
{
if (c->sz == 0)
{
printf("通讯录已空\n");
return;
}
char name[MAX_NAME];
printf("请输入要删除的人的姓名:\n");
scanf("%s", name);
int pos = FindContact(c,name);
if (pos == -1)
{
printf("查无此人\n");
}
else
{
for (int i = pos; i < c->sz - 1; i++)
{
c->data[i] = c->data[i + 1];
}
printf("删除成功\n");
c->sz--;
}
}
int FindContact(Contact* c,char* name)//找到返回0,没找到返回-1
{
int pos = 0;
for (int i = 0; i < c->sz; i++)
{
pos = strcmp(name, c->data[i].name);
if (pos == 0)
{
return pos;
}
}
return -1;
}
void SearchContact(Contact* c)
{
if (c->sz == 0)
{
printf("通讯录已空\n");
return;
}
char name[MAX_NAME];
printf("请输入要删除的人的姓名:\n");
scanf("%s", name);
int pos = FindContact(c, name);
if (pos == -1)
{
printf("查无此人\n");
}
else
{
printf("%20s %5s %5s %15s %20s\n", "姓名", "年龄", "性别", "号码", "地址\n");
printf("%20s %5d %5s %15s %20s\n", c->data[pos].name, c->data[pos].age, c->data[pos].sex, c->data[pos].number, c->data[pos].address);
}
}
int FindContact(Contact* c,char* name) //找到返回0,没找到返回-1
{
int pos = 0;
for (int i = 0; i < c->sz; i++)
{
pos = strcmp(name, c->data[i].name);
if (pos == 0)
{
return pos;
}
}
return -1;
}
void ModifyContact(Contact* c)
{
if (c->sz == 0)
{
printf("通讯录已空\n");
return;
}
char name[MAX_NAME];
printf("请输入要修改的人的姓名:\n");
scanf("%s", name);
int pos = FindContact(c, name);
if (pos == -1)
{
printf("查无此人\n");
}
else
{
printf("请输入姓名\n");
scanf("%s", c->data[pos].name);
printf("请输入年龄\n");
scanf("%d", &(c->data[pos].age));
printf("请输入性别\n");
scanf("%s", c->data[pos].sex);
printf("请输入号码\n");
scanf("%s", c->data[pos].number);
printf("请输入地址\n");
scanf("%s", c->data[pos].address);
printf("修改成功!!\n");
}
}
int CmpPeoAge(const void* a, const void* b)
{
return ((PeoInfo*)a)->age - ((PeoInfo*)b)->age;
}
void SortContact(Contact* c)
{
qsort(c->data, c->sz, sizeof(PeoInfo), CmpPeoAge);
printf("排序完成\n");
}
void ClearContact(Contact* c)
{
memset(c->data, 0, c->sz); //将所有空间置0
PeoInfo* ptr = (PeoInfo*)realloc(c->data, DEFAULT_SZ*sizeof(PeoInfo));
//重新申请一块初始大小的空间
if (ptr == NULL)
{
printf("清理失败\n");
return;
}
c->sz = 0;
c->Capable = DEFAULT_SZ;
c->data = ptr;
printf("清理成功\n");
}
void SaveContact(Contact* c)
{
FILE* pf = fopen("ContactData.txt", "wb");
if (pf == NULL)
{
perror("fopen:");
return;
}
for (int i = 0; i < c->sz; i++)
{
fwrite(c->data+i, sizeof(PeoInfo), 1, pf);
}
fclose(pf);
pf = NULL;
printf("保存成功");
}
void ExitContact(Contact* c)
{
free(c->data);
c->data = NULL;
c->Capable = 0;
c->sz = 0;
}
为了使代码更有阅读性,我们不建议把所有函数写在一个文件里,所以这里分成三个文件,模块化管理
这个文件包含程序的主体构思,程序用到的一系列函数我们封装在其他文件夹,这里只需要引入头文件即可
#include "contact.h"
void menu()
{
printf("********************************\n");
printf("***** 1.Add 2.Del *****\n");
printf("***** 3.Search 4.Modif *****\n");
printf("***** 5.Show 6.Sort *****\n");
printf("***** 7.clear 0.Exit *****\n");
printf("********************************\n");
}
enum option
{
Exit,
Add,
Del,
Search,
Modify,
Show,
Sort,
Clear
};
int main()
{
int input = 0;
Contact con;
InitContact(&con);
do
{
menu();
printf("请选择要进行的操作\n");
scanf("%d", &input);
switch (input)
{
case Add:
AddContact(&con);
break;
case Del:
DelContact(&con);
break;
case Search:
SearchContact(&con);
break;
case Modify:
ModifyContact(&con);
break;
case Show:
ShowContact(&con);
break;
case Sort:
SortContact(&con);
break;
case Clear:
ClearContact(&con);
break;
case Exit:
SaveContact(&con);
ExitContact(&con);
printf("退出成功\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
所有对通讯录进行操作的函数全部放在这里
#include "contact.h"
//加载通讯录
void LoadingContact(Contact* c)
{
FILE* pf = fopen("ContactData.txt", "rb");
if (pf == NULL)
{
perror("loadingContact:fopen:");
return;
}
while (fread(c->data+c->sz, sizeof(PeoInfo), 1, pf))
{
c->sz++;
CheckContact(c);
}
fclose(pf);
pf = NULL;
}
//初始化通讯录
void InitContact(Contact* c)
{
PeoInfo* ptr = (PeoInfo*)malloc(sizeof(PeoInfo) * DEFAULT_SZ);
if (ptr == NULL)
{
printf("%s", strerror(errno));
return;
}
c->sz = 0;
c->Capable = DEFAULT_SZ;
c->data = ptr;
LoadingContact(c);
}
//静态添加联系人
//void AddContact(Contact* c)
//{
// if (c->sz == 100)
// {
// printf("人数已满,不能继续添加\n");
// return;
// }
// printf("请输入要添加的联系人\n");
// printf("请输入姓名\n");
// scanf("%s", c->data[c->sz].name);
// printf("请输入年龄\n");
// scanf("%d", &(c->data[c->sz].age));
// printf("请输入性别\n");
// scanf("%s", c->data[c->sz].sex);
// printf("请输入号码\n");
// scanf("%s", c->data[c->sz].number);
// printf("请输入地址\n");
// scanf("%s", c->data[c->sz].address);
// c->sz++;
//}
void CheckContact(Contact* c)
{
if (c->sz == c->Capable)
{
PeoInfo* ptr = (PeoInfo*)realloc(c->data, (DEFAULT_INC + c->Capable) * sizeof(PeoInfo));
if (ptr == NULL)
{
printf("%s", strerror(errno));
return;
}
c->Capable = c->Capable + DEFAULT_INC;
c->data = ptr;
printf("扩容成功\n");
}
}
//动态添加联系人
void AddContact(Contact* c)
{
CheckContact(c);
printf("请输入要添加的联系人\n");
printf("请输入姓名\n");
scanf("%s", c->data[c->sz].name);
printf("请输入年龄\n");
scanf("%d", &(c->data[c->sz].age));
printf("请输入性别\n");
scanf("%s", c->data[c->sz].sex);
printf("请输入号码\n");
scanf("%s", c->data[c->sz].number);
printf("请输入地址\n");
scanf("%s", c->data[c->sz].address);
c->sz++;
}
int FindContact(Contact* c, char* name)
{
int pos = 0;
for (int i = 0; i < c->sz; i++)
{
int pos1 = strcmp(name, c->data[i].name);
if (pos1 == 0)
{
return pos;
}
pos++;
}
return -1;
}
void DelContact(Contact* c)
{
if (c->sz == 0)
{
printf("通讯录已空\n");
return;
}
char name[MAX_NAME];
printf("请输入要删除的人的姓名:\n");
scanf("%s", name);
int pos = FindContact(c, name);
if (pos == -1)
{
printf("查无此人\n");
}
else
{
for (int i = pos; i < c->sz - 1; i++)
{
c->data[i] = c->data[i + 1];
}
printf("删除成功\n");
c->sz--;
}
}
void ShowContact(Contact* c)
{
printf("%2s %20s %5s %5s %15s %20s\n","序号", "姓名", "年龄", "性别", "号码", "地址\n");
for (int i = 0; i < c->sz; i++)
{
printf("%2d %20s %5d %5s %15s %20s\n", i+1,c->data[i].name, c->data[i].age, c->data[i].sex, c->data[i].number, c->data[i].address);
}
}
void SearchContact(Contact* c)
{
if (c->sz == 0)
{
printf("通讯录已空\n");
return;
}
char name[MAX_NAME];
printf("请输入要删除的人的姓名:\n");
scanf("%s", name);
int pos = FindContact(c, name);
if (pos == -1)
{
printf("查无此人\n");
}
else
{
printf("%20s %5s %5s %15s %20s\n", "姓名", "年龄", "性别", "号码", "地址\n");
printf("%20s %5d %5s %15s %20s\n", c->data[pos].name, c->data[pos].age, c->data[pos].sex, c->data[pos].number, c->data[pos].address);
}
}
void ModifyContact(Contact* c)
{
if (c->sz == 0)
{
printf("通讯录已空\n");
return;
}
char name[MAX_NAME];
printf("请输入要修改的人的姓名:\n");
scanf("%s", name);
int pos = FindContact(c, name);
if (pos == -1)
{
printf("查无此人\n");
}
else
{
printf("请输入姓名\n");
scanf("%s", c->data[pos].name);
printf("请输入年龄\n");
scanf("%d", &(c->data[pos].age));
printf("请输入性别\n");
scanf("%s", c->data[pos].sex);
printf("请输入号码\n");
scanf("%s", c->data[pos].number);
printf("请输入地址\n");
scanf("%s", c->data[pos].address);
printf("修改成功!!\n");
}
}
int CmpPeoAge(const void* a, const void* b)
{
return ((PeoInfo*)a)->age - ((PeoInfo*)b)->age;
}
void SortContact(Contact* c)
{
qsort(c->data, c->sz, sizeof(PeoInfo), CmpPeoAge);
printf("排序完成\n");
}
void ClearContact(Contact* c)
{
memset(c->data, 0, c->sz);
PeoInfo* ptr = (PeoInfo*)realloc(c->data, DEFAULT_SZ*sizeof(PeoInfo));
if (ptr == NULL)
{
printf("清理失败\n");
return;
}
c->sz = 0;
c->Capable = DEFAULT_SZ;
c->data = ptr;
printf("清理成功\n");
}
void ExitContact(Contact* c)
{
free(c->data);
c->data = NULL;
c->Capable = 0;
c->sz = 0;
}
void SaveContact(Contact* c)
{
FILE* pf = fopen("ContactData.txt", "wb");
if (pf == NULL)
{
perror("fopen:");
return;
}
for (int i = 0; i < c->sz; i++)
{
fwrite(c->data+i, sizeof(PeoInfo), 1, pf);
}
fclose(pf);
pf = NULL;
printf("保存成功");
}
将主程序所需要的函数全部在头文件中声明,增加代码阅读性
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_NUMBER 15
#define MAX_ADDRESS 20
typedef struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char number[MAX_NUMBER];
char address[MAX_ADDRESS];
}PeoInfo;
typedef struct Contact
{
PeoInfo data[100];
int sz;
}Contact;
void InitContact(Contact *c);
void AddContact(Contact *c);
void DelContact(Contact *c);
void ShowContact(Contact *c);
void SearchContact(Contact *c);
void ModifyContact(Contact *c);
void SortContact(Contact* c);
这就是实现通讯录的全部内容了,创作不易,还请各位小伙伴多多点赞关注收藏⭐,以后也会更新各种小游戏还有关于c语言的博客,撒花!