用C语言实现一个静态通讯录
一、问题描述及文章声明
1. 问题描述
通过C语言代码实现一个静态通讯录的编写
2. 文章声明
如果您想系统学会如何编写静态通讯录程序,请先认真理解思路讲解中的整体思路分析,而后按照每个步骤认真学习,相信您会有所收获。
如果您只是想复制代码,直接跳到代码实现步骤即可。
二、基本流程
1. 在电脑安装Visual Studio 2022等编译器
可于b站查找按照流程
2. 创建一个新项目
(1). 在新建的项目中创建三个文件(如图所示)
test.c
文件用于测试通讯录的功能
contact.c
文件用于通讯录相关的实现
contact.h
文件用于通讯录的相关声明
三、思路讲解
1. 编写代码时的整体思路分析
当你产生对一件事的想法时,你需要先基本捋清思路,而后在实行的时候不断进行优化,编写三子棋代码也是如此。
首先我们需要明白静态通讯录代码的整体框架。
- 当用户打开通讯录时,首先需要有个选择窗口让用户进行选择,因此我们首先需要进行菜单界面的编写。
- 而当用户使用通讯录之时,我们需要考虑到用户可能需要的选项,因此我们在菜单界面给用户提供了7个选择,即增、删、改、查、展示、排序、和退出通讯录。
- 为了对联系人进行更详细的记录以便于用户使用,我们需要先创建一个 PeoInfo 的结构体变量,存储人的信息
- 我们需要初步预估用户的所需要存储到通讯录的人数,从而给出一个合理的通讯录空间让用户对联系人进行存储,因此我们需要对通讯录进行初始化。
- 为了更方便我们看到代码运行结果,因此我们在设置完增加联系人的函数之后,便先设置了打印通讯录中的信息的函数,并在每一段代码书写后运行展示效果,以确保每段代码的正确性。
- 当考虑完可能出现的问题后,便可开始进行对对通讯录的编写。
2. 代码的具体分布编写
(1). 菜单函数的设置
下面展示一些
菜单设置代码片
。
菜单函数设置—— 在test.c
文件下
通过设置菜单函数,使用户能够更加直观得观看到通讯录所具备的功能
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
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;//初始化input
do
{
menu();//设置菜单函数
printf("请选择:>");//提醒用户选择
scanf("%d", &input);//提醒用户进行选择
switch (input)//通过选择分支结果调用相应的函数
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
}
} while (input);
}
(2). 相关结构体的声明
相关结构体的设置——在
contact.h
文件下声明struct PeoInfo()
和struct Contact()
结构体变量并重命名以方便使用
考虑到每个人都具有多种属性,如:年龄、性别、电话等,因此我们定义一个人的信息的结构体变量
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
//类型声明
//人的信息
typedef struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
typedef struct Contact
{
PeoInfo data[MAX];//存放人的信息
int count;//统计通讯录实际人数
}Contact;
(3). 通讯录初始化
初始化通讯录函数设置——在
contact.h
文件下先定义InitContact()
函数
#include <assert.h>//需要在contact.c文件下先判断是否为空指针
//[可在该网址查看函数](https://cplusplus.com/reference/cassert/assert/)
#include <string.h>//需要在contact.c文件下使用memset对通讯录内容初始化为0
//[可在该网址查看函数](https://cplusplus.com/reference/cstring/memset/)
void InitContact(Contact* pc);//函数声明
初始化通讯录函数设置—— 在
contact.c
文件下
void InitContact(Contact* pc)
{
assert(pc);
pc->count = 0;//因为是结构体指针,所以用pc->count指向结构体Contact中的结构体变量count
memset(pc->data, 0, sizeof(pc->data));
}
初始化通讯录函数的调用—— 在
test.c
文件下
int main()
{
int input = 0;//初始化input
Contact con;//通讯录
//初始化通讯录
InitContact(&con);
do {···} while (input);
}
(4). 增加联系人到通讯录中
增加联系人的函数设置——在
contact.h
文件下先定义AddContact()
函数
在设置增加联系人的函数时,由于目前我们所设置的通讯录为静态的,因此我们需要考虑到通讯录是否已经满了的情况,如果已经满了,便直接用 return 跳出该函数
//增加联系人到通讯录中
void AddContact(Contact* pc);
增加联系人的函数设置——在
contact.c
文件
void AddContact(Contact* pc)
{
assert(pc);
if (pc->count == MAX)
{
printf("通讯录已满\n");
}
printf("请输入名字:>");
scanf("%s", pc->data[pc->count].name);//当count为0时,更改结构体数组中第一个结构体变量中的名字
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->count].age));//当count为0时,更改结构体数组中第一个结构体变量中的年龄
printf("请输入性别:>");
scanf("%s", pc->data[pc->count].sex);//当count为0时,更改结构体数组中第一个结构体变量中的性别
printf("请输入电话:>");
scanf("%s", pc->data[pc->count].tele);//当count为0时,更改结构体数组中第一个结构体变量中的电话
printf("请输入地址:>");
scanf("%s", pc->data[pc->count].addr);//当count为0时,更改结构体数组中第一个结构体变量中的地址
pc->count++;//Contact结构体变量中的总人数加1
printf("增加成功\n");
}
(4). 打印通讯录中的信息
打印通讯录中的信息的函数设置——在
contact.h
文件下先定义ShowContact()
函数
为了能够通过调试代码来确定每个函数的设置是否正确,因此我们在设置完增加联系人函数之后优先设置打印通讯录中的信息的函数
//打印通讯录中的信息
void ShowContact(Contact* pc);
当我们增加联系人到通讯录中之后,我们需要查看是否增加成功,因此先编写打印通讯中的信息的函数
打印通讯录中的信息的函数设置——在contact.c
文件下
void ShowContact(Contact* pc)
{
assert(pc);
int i = 0;
printf("%-20s\t%-5s\t%-20s\t%-12s\t%-30s\n","名字", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->count; i++)
{
printf("%-20s\t%-5d\t%-20s\t%-12s\t%-30s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
(5). 删除指定联系人
删除指定联系人的函数设置——在
contact.h
文件下先定义DelContact()
函数
//删除指定联系人
void DelContact(Contact* pc);
删除指定联系人的函数设置——在
contact.c
文件下
int FindByName(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->count; i++)
{
//遍历结构体数组,查看是否有相同的名字,存在则返回该元素的下标
//也可以用同样的方法通过判断其他信息进行删除
if (0 == strcmp(pc->data[i].name, name))
{
return i;
}
}
return -1;
}
void DelContact(Contact* pc)
{
assert(pc);
char name[MAX_NAME] = { 0 };
if (pc->count == 0)
{
printf("通讯录为空,没有信息可以删除\n");
return;
}
printf("请输入要删除人的名字:>");
scanf("%s", name);
//删除
//1.查找
int pos = FindByName(pc,name);//调用函数判断将要删除的联系人是否存在
if (pos == -1)
{
printf("要删除的人不存在\n");
return;
}
//2.删除
int i = 0;
for (i = pos; i < pc->count-1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->count--;//通讯录中总人数在删除后需要减一
printf("删除成功\n");
}
(6). 查找指定联系人
查找指定联系人的函数设置——在
contact.h
文件下先定义SearchContact()
函数
void SearchContact(Contact* pc);
查找指定联系人的函数设置——在
contact.c
文件下
void SearchContact(Contact* pc)
{
assert(pc);
char name[MAX_NAME] = { 0 };
if (pc->count == 0)
{
printf("通讯录为空,没有信息可以修改\n");
return;
}
printf("请输入要查找的名字:>");
scanf("%s", name);
//查看
//1.查找
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
//2.打印
printf("%-20s\t%-5s\t%-10s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
printf("%-20s\t%-5d\t%-10s\t%-12s\t%-30s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);
}
(6). 修改指定联系人
修改指定联系人的函数设置——在
contact.h
文件下先定义SearchContact()
函数
void SearchContact(Contact* pc);
修改指定联系人的函数设置——在
contact.c
文件下
void ModifyContact(Contact* pc)
{
assert(pc);
char name[MAX_NAME] = { 0 };
printf("请输入要修改的名字:>");
scanf("%s", name);
//1.查找
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要修改的人不存在\n");
return;
}
//2.修改
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].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
(6). 排序通讯录中内容
排序通讯录中内容的函数设置——在
contact.h
文件下先定义SortContact()
函数
//排序通讯录中内容
//按照名字来排序
//按照年龄来排序
//...
void SortContact(Contact* pc);
排序通讯录中内容的函数设置——在
contact.c
文件下
//[qsort的用法](https://cplusplus.com/reference/cstdlib/qsort/)
int cmp_peo_by_name(const void* e1,const void*e2)//设置比较函数
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
assert(pc);
qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_peo_by_name);
printf("排序成功\n");
}
(7). 效果展示
四、代码实现
test.c
总代码展示
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
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;//初始化input
Contact con;//通讯录
//初始化通讯录
InitContact(&con);
do
{
menu();//设置菜单函数
printf("请选择:>");//提醒用户选择
scanf("%d", &input);//提醒用户进行选择
switch (input)//通过选择分支结果调用相应的函数
{
case 1:
AddContact(&con);
break;
case 2:
DelContact(&con);
break;
case 3:
SearchContact(&con);
break;
case 4:
ModifyContact(&con);
break;
case 5:
ShowContact(&con);
break;
case 6:
SortContact(&con);
break;
case 7:
break;
}
} while (input);
}
contact.c
总代码展示
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void InitContact(Contact* pc)
{
assert(pc);
pc->count = 0;
memset(pc->data, 0, sizeof(pc->data));
}
void AddContact(Contact* pc)
{
assert(pc);
if (pc->count == MAX)
{
printf("通讯录已满\n");
}
printf("请输入名字:>");
scanf("%s", pc->data[pc->count].name);//当count为0时,更改结构体数组中第一个结构体变量中的名字
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->count].age));//当count为0时,更改结构体数组中第一个结构体变量中的年龄
printf("请输入性别:>");
scanf("%s", pc->data[pc->count].sex);//当count为0时,更改结构体数组中第一个结构体变量中的性别
printf("请输入电话:>");
scanf("%s", pc->data[pc->count].tele);//当count为0时,更改结构体数组中第一个结构体变量中的电话
printf("请输入地址:>");
scanf("%s", pc->data[pc->count].addr);//当count为0时,更改结构体数组中第一个结构体变量中的地址
pc->count++;//Contact结构体变量中的总人数加1
printf("增加成功\n");
}
void ShowContact(Contact* pc)
{
assert(pc);
int i = 0;
printf("%-20s\t%-5s\t%-20s\t%-12s\t%-30s\n","名字", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->count; i++)
{
printf("%-20s\t%-5d\t%-20s\t%-12s\t%-30s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
int FindByName(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->count; i++)
{
if (0 == strcmp(pc->data[i].name, name))
{
return i;
}
}
return -1;
}
void DelContact(Contact* pc)
{
assert(pc);
char name[MAX_NAME] = { 0 };
if (pc->count == 0)
{
printf("通讯录为空,没有信息可以删除\n");
return;
}
printf("请输入要删除人的名字:>");
scanf("%s", name);
//删除
//1.查找
int pos = FindByName(pc,name);
if (pos == -1)
{
printf("要删除的人不存在\n");
return;
}
//2.删除
int i = 0;
for (i = pos; i < pc->count-1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->count--;
printf("删除成功\n");
}
void SearchContact(Contact* pc)
{
assert(pc);
char name[MAX_NAME] = { 0 };
if (pc->count == 0)
{
printf("通讯录为空,没有信息可以修改\n");
return;
}
printf("请输入要查找的名字:>");
scanf("%s", name);
//查看
//1.查找
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
//2.打印
printf("%-20s\t%-5s\t%-10s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
printf("%-20s\t%-5d\t%-10s\t%-12s\t%-30s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);
}
void ModifyContact(Contact* pc)
{
assert(pc);
char name[MAX_NAME] = { 0 };
printf("请输入要修改的名字:>");
scanf("%s", name);
//1.查找
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要修改的人不存在\n");
return;
}
//2.修改
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].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
int cmp_peo_by_name(const void* e1,const void*e2)
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
assert(pc);
qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_peo_by_name);
printf("排序成功\n");
}
contact.h
总代码展示
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
//类型声明
//人的信息
typedef struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
typedef struct Contact
{
PeoInfo data[MAX];//存放人的信息
int count;//统计通讯录实际人数
}Contact;
void InitContact(Contact* pc);
//增加联系人到通讯录中
void AddContact(Contact* pc);
//打印通讯中的信息
void ShowContact(Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
//排序通讯录中内容
//按照名字来排序
//按照年龄来排序
//...
void SortContact(Contact* pc);