小程序|通讯录小程序(C语言)
通讯录小程序(C语言)
- 程序介绍
- 实现思路和内容概括
- 代码实现
-
- 打印菜单
- 定义通讯录
- 初始化通讯录函数
- 添加联系人函数
- 显示通讯录函数
- 查找通讯录函数
- 删除联系人
- 查找指定联系人
- 修改指定联系人信息
- 排序(按姓名)
- 完整代码
-
- contact.h
- contact.c
- test.c
- 运行展示
- 总结
程序介绍 【小程序|通讯录小程序(C语言)】通过前面学习我们可以实现通讯录小程序的代码,首先,我们需要创建一个通讯录,通讯录中存放1000个人的信息,信息包括:名字,性别,年龄,电话,住址。通讯录主要由5个功能:增加联系人、删除联系人、修改联系人、查找联系人、按名称子排序。下面我们来看实现过程。
实现思路和内容概括 首先我们将完整的代码分为3个部分——contact.h(头文件)、contact.c(函数部分)、test.c(主函数实现部分)。我们会创建一个大的框架,将菜单放入其中,菜单有7个选项:1.add 2.del 3.search 4.modify 5.show 6.sort 0.exit
输入“1”,添加联系人信息,输入“2”,删除指定联系人信息,输入“3”,查找指定联系人信息(按姓名查找并打印),输入“4”,修改指定联系人信息(按姓名查找),输入“5”,打印当前的通讯录所有联系人,输入“6”,将通讯录所有联系人按姓名排序。输入“0”,退出通讯录。
代码实现 打印菜单
void menu()
{ printf("****************************\n");
printf("**** 1.add2.del****\n");
printf("**** 3.search4.modify ****\n");
printf("**** 5.show6.sort****\n");
printf("**** 0.exit****\n");
printf("****************************\n");
printf("****************************\n");
}
enum Option
{ EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
int main()
{ int input=0;
//创建一个通讯录
struct Contact con;
//初始化通讯录
InitContact(&con);
do
{menu();
printf("请选择:>");
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:
SortContactByName(&con);
break;
case EXIT:
printf("退出通讯录。\n");
break;
default:
printf("选择错误!\n");
break;
}
} while (input);
return 0;
}
我们利用枚举类型将EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT放入其中,因为枚举类型中的成员属于常量所以具有常量的属性,我们可以利用此属性运用到switch上,这样就提高了代码的可读性。利用do while循环,我们先打印menu()函数,再利用input变量,只要输入非0,都会打印菜单,只是效果不同。
定义通讯录
//描述人的信息
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 1000
struct PeoInfo
{ char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
};
//通讯录
struct Contact
{ struct PeoInfo data[MAX];
//1000个人的信息存放进data数组中
int sz ;
//记录当前存放进通讯录中的有效信息的个数
};
定义一个通讯录需要两个结构体,struct PeoInfo结构体是描述一个人的信息,struct Contact结构体是通讯录本身,我们将struct PeoInfo中的个人信息存放在struct Contact结构体中以实现联系,也就是struct Contact的成员data[1000]是struct PeoInfo结构体类型,data[1000]是一个结构体类型的数组,里面有name[20],age,sex[5],tele[12],addr[30]。
初始化通讯录函数
void InitContact(struct Contact* pc)
{ pc->sz = 0;
//默认没有信息
//memset(pc->data, 0, MAX * sizeof(struct PeoInfo));
memset(pc->data, 0, sizeof(pc->data));
}
当我们定义一个通讯录结构体时,数值都是随机值,因此我们需要初始化,将通讯录所有的信息数据都变成“0”,这里使用了memset()函数,我们在内存函数博客中介绍了这个函数,不在细说。具体实现原理可以看前面的博客内存函数(C语言)
添加联系人函数
void AddContact(struct Contact* pc)
{ if (pc->sz == MAX)
{printf("通讯录已满!\n");
}
else
{printf("请输入名字:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pc->sz].addr );
//提示添加成功
printf("添加成功\n");
pc->sz++;
}
}
AddContact()函数,首先先进行判断,sz(记录当前存放进通讯录中的有效信息的个数)是否等于MAX(1000),如果有,则打印通讯录已满,如果没有则按要求输入信息,并提示添加成功,sz++。
显示通讯录函数
void ShowContact(struct Contact* pc)
{ int i = 0;
printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
for (i = 0;
i < pc->sz;
i++)
{//打印每一个数据
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
在ShowContact()函数中,我们先打印标题"name", “age”, “sex”, “tele”, “addr”,然后利用for循环将信息一一对应标题都打印下来。
查找通讯录函数
int FindContactByName(const struct Contact* pc, const char *name)
{ int i = 0;
for (i = 0;
i < pc->sz;
i++)
{if (strcmp(pc->data[i].name, name) == 0)
{return i;
}
}
//找不到
return -1;
}
FindContactByName()函数的基本实现是通过strcmp()函数实现的,利用for循环,找到查找的名字于通讯录名字相等的此时i的值,并返回i的值,此时i的值正是data数组的下标,方便后续操作,关于strcmp()函数实现原理可以看以前博客字符与字符串函数(C语言)。
删除联系人
void DelContact(struct Contact* pc)
{ if (pc->sz == 0)
{printf("通讯录为空,无法删除\n");
return;
}
char name[NAME_MAX] = {
0 };
printf("请输入要删除人的名字:>");
scanf("%s", name);
//查找
int pos = FindContactByName(pc, name);
if (pos == -1)
{printf("指定的联系人不存在\n");
}
else
{//删除
int j = 0;
for (j = pos;
j < pc->sz-1;
j++)
{pc->data[j] = pc->data[j + 1];
}
pc->sz--;
//提示
printf("删除成功\n");
}
}
DelContact()函数和AddContact()函数类似,但是比添加联系人要复杂,删除联系人先再找到指定的联系人,在进行操作,因此,DelContact()函数中运用了查找通讯录函数,利用名字进行比较找出指定的联系人,在进行删除时,并不是直接删除,而是利用后一个信息将前一个信息的覆盖,如此达到删除联系人的信息。
查找指定联系人
void SearchContact(const struct Contact* pc)
{ char name[NAME_MAX] = {
0 };
printf("输入要查找人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (-1 == pos)
{printf("查无此人\n");
}
else
{printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
}
}
SearchContact()函数是在FindContactByName()函数的基础之上增加了打印的功能,如果没有查找到指定的联系人打印“查无此人”,否则打印出该联系人的所有信息。
修改指定联系人信息
void ModifyContact(struct Contact* pc)
{ char name[NAME_MAX] = {
0 };
printf("输入要修改人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (-1 == pos)
{printf("要修改的人不存在\n");
}
else
{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);
}
}
ModifyContact()函数是利用FindContactByName()函数先将想要修改的联系人找到,然后输入新的所有信息来覆盖原来的信息。
排序(按姓名)
int cmp_name(const void* e1, const void* e2)
{ return strcmp(((struct Contact*)e1)->data->name , ((struct Contact*)e2)->data->name);
}
void SortContactByName(struct Contact* pc)
{ qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
printf("排序成功\n");
}
排序运用到了qsort()函数,这个函数可以排序任意类型的数据,因此结构体也可以。但是需要引用到头文件#include
qsort()函数:
形式:void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) )
解释:qsort函数实现了一种快速排序算法,用于对num元素数组进行排序,每个元素的宽度为字节。参数base是指向要排序的数组的基的指针。qsort用已排序的元素覆盖此数组。参数compare是指向用户提供的例程的指针,该例程比较两个数组元素并返回指定其关系的值。
也就是说,*base是一个指针,num是要排序的个数,width是排序元素的大小,int (__cdecl *compare )(const void *elem1, const void *elem2 ) 是一个函数,这个函数就是用来判断怎样比较的。以写的代码为例,pc是指针指向的是struct Contact con结构体,pc->sz是记录当前存放进通讯录中的有效信息的个数,也就对应了打印的个数,sizeof(pc->data[0])是个人信息的结构体的大小,cmp_name()函数是按名字来进行排序。
完整代码 contact.h
#include
#include
#include
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 1000//描述人的信息
struct PeoInfo
{ char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
};
//通讯录
struct Contact
{ struct PeoInfo data[MAX];
//1000个人的信息存放进data数组中
int sz ;
//记录当前存放进通讯录中的有效信息的个数
};
//初始化通讯录
void InitContact(struct Contact* pc);
//增加联系人
void AddContact(struct Contact* pc);
//显示通讯录
void ShowContact(struct Contact* pc);
//删除联系人
void DelContact(struct Contact* pc);
//查找指定联系人
void SearchContact(const struct Contact* pc);
//修改指定联系人
void ModifyContact(struct Contact* pc);
//按姓名排序通讯录
void SortContactByName(struct Contact* pc);
用#define定义的常量能够方便代码的修改,增加了代码的维护性。
contact.c
#include"contact.h"
void InitContact(struct Contact* pc)
{ pc->sz = 0;
//默认没有信息
//memset(pc->data, 0, MAX * sizeof(struct PeoInfo));
memset(pc->data, 0, sizeof(pc->data));
}void AddContact(struct Contact* pc)
{ if (pc->sz == MAX)
{printf("通讯录已满!\n");
}
else
{printf("请输入名字:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pc->sz].addr );
//提示添加成功
printf("添加成功\n");
pc->sz++;
}
}void ShowContact(struct Contact* pc)
{ int i = 0;
printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
for (i = 0;
i < pc->sz;
i++)
{//打印每一个数据
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}int FindContactByName(const struct Contact* pc, const char *name)
{ int i = 0;
for (i = 0;
i < pc->sz;
i++)
{if (strcmp(pc->data[i].name, name) == 0)
{return i;
}
}
//找不到
return -1;
}void DelContact(struct Contact* pc)
{ if (pc->sz == 0)
{printf("通讯录为空,无法删除\n");
return;
}
char name[NAME_MAX] = {
0 };
printf("请输入要删除人的名字:>");
scanf("%s", name);
//查找
int pos = FindContactByName(pc, name);
if (pos == -1)
{printf("指定的联系人不存在\n");
}
else
{//删除
int j = 0;
for (j = pos;
j < pc->sz-1;
j++)
{pc->data[j] = pc->data[j + 1];
}
pc->sz--;
//提示
printf("删除成功\n");
}
}void SearchContact(const struct Contact* pc)
{ char name[NAME_MAX] = {
0 };
printf("输入要查找人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (-1 == pos)
{printf("查无此人\n");
}
else
{printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
printf("%15s\t%5d\t%8s\t%15s\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(struct Contact* pc)
{ char name[NAME_MAX] = {
0 };
printf("输入要修改人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (-1 == pos)
{printf("要修改的人不存在\n");
}
else
{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);
}
}
int cmp_name(const void* e1, const void* e2)
{ return strcmp(((struct Contact*)e1)->data->name , ((struct Contact*)e2)->data->name);
}
void SortContactByName(struct Contact* pc)
{ qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
printf("排序成功\n");
}
存放用到的所有函数,需要引用头文件#include"contact.h"。
test.c
#include "contact.h"
void menu()
{ printf("****************************\n");
printf("**** 1.add2.del****\n");
printf("**** 3.search4.modify ****\n");
printf("**** 5.show6.sort****\n");
printf("**** 0.exit****\n");
printf("****************************\n");
printf("****************************\n");
}
enum Option
{ EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
int main()
{ int input=0;
//创建一个通讯录
struct Contact con;
//初始化通讯录
InitContact(&con);
do
{menu();
printf("请选择:>");
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:
SortContactByName(&con);
break;
case EXIT:
printf("退出通讯录。\n");
break;
default:
printf("选择错误!\n");
break;
}
} while (input);
return 0;
}
主函数部分,这个部分也是实现部分,进入函数,先创建一个通讯录struct Contact con,然后初始化,再根据所选的input,进行个系列的操作,以此达到通讯录的增删改查等功能。
运行展示
文章图片
总结 关于通讯录其实还有很多改进的地方,这只是最简易的版本,还可以加入文件导入,动态版本等等,相对于改进的版本,这是最简易也是最好理解的。有难度的在于qsort()函数的理解,当然我们也可以采用自己实现的排序冒泡或者快排都可以。好了通讯录小程序也可以说的上将C语言中语法的大部分内容都用了一边,对于编程能力的提升和语法的理解是有着很大的帮助的,希望大家能够抽出时间将代码敲上一敲。如果有什么错误或者建议,希望各位能够提出建议,谢谢各位!
推荐阅读
- 一个小故事,我的思考。
- 家乡的那条小河
- 一个人的碎碎念
- 野营记-第五章|野营记-第五章 讨伐梦魇兽
- 昨夜小楼听风
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 基于微信小程序带后端ssm接口小区物业管理平台设计
- 2019.4.18感恩日记
- 那件我们忽略的小事叫感恩
- 你有婚内虐待行为吗()