通讯录的功能
今天实现的通讯录功能主要有:
0.退出通讯录
1.添加联系人
2.删除指定联系人
3.查找指定联系人
4.修改指定联系人
5.显示当前通讯录
6.联系人排序(名字和年龄)
7.清空通讯录
通讯录的主函数框架
我们把通讯录分为三个文件来实现,第一个test.c文件来写通讯录主要框架,第二个contact.c文件来实现函数功能,第三个contact.h文件来引用头文件和函数的声明。首先我们需要把通讯录的框架给实现出来,之后逐步实现每个函数的功能。
#include"contact.h" enum Option { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT, EMPTY }; void menu(); int main() { int input = 0; Contact con ; InitContact(&con); do { menu(); printf("请输入你想选择的操作:"); scanf("%d", &input); switch (input) { case EXIT: printf("退出通讯录成功"); break; 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 EMPTY: InitContact(&con); printf("清空通讯录成功\n"); break; default: printf("输入错误\n"); break; } } while (input); return 0; }
我们用do while循环来实现通讯录的主体框架,我们使用枚举给每个操作选项赋值,可读性更高。
contact.h(头文件引用、函数声明和自定义值大小)
我们先来把该声明的函数声明一下,并且引用需要的头文件,设置一些需要重复使用的值,以及对结构体的声明。
#define _CRT_SECURE_NO_WARNINGS #pragma once #include<stdio.h> #include<assert.h> #include<string.h> #include<stdlib.h> #define NAME_MAX 20 #define SEX_MAX 10 #define TELE_MAX 12 #define ADDR_MAX 30 #define MAX 100 typedef struct PeoInfo { char name[NAME_MAX]; int age; char sex[SEX_MAX]; char tele[TELE_MAX]; char addr[ADDR_MAX]; }PeoInfo; typedef struct Contact { PeoInfo data[MAX];//存放成员数据 int sz;//记录当前通讯录人数 }Contact; void menu(); void InitContact(Contact* pc); void ADDContact(Contact* pc); void SHOWContact(const Contact* pc); void DELContact(Contact* pc); void SearchContact(Contact* pc); void ModifyContact(Contact* pc); void SortContact(Contact* pc);
这样我们就把整个通讯录引用函数的头文件全部包含在了contact.h中,并且定义了一个PeoInfo的结构体,里面存放了一个联系人的名字、年龄、性别、电话、住址。并将该结构体命名为PeoInfo。之后我们再定义一个结构体Contact,里面用PeoInfo定义一个数组,这样就能存放许多联系人的数据,并且为了记录存放了多少个联系人,定义一个整形sz来记录,并且把该结构体命名为Contact。
通讯录函数功能的实现
接下来我们一个一个来实现通讯录的函数功能,但在此之前,我们需要在主函数中使用Contact来定义一个通讯录出来,因为定义出来的通讯录里面的值是随机的,所以我们需要初始化通讯录,把里面的值统统赋为0。
int input = 0; Contact con ; InitContact(&con);
也就是这写代码,首先input是我们进行选择操作所定义的整形值,con是定义出来的通讯录,
而InitContact函数则是用来初始化con的,所以我们把con的地址传过去。
接下来我们来看一下初始化函数功能的实现。
void InitContact(Contact* pc) { assert(pc);//断言传过来指针非空 pc->sz = 0;//给sz赋值为0 memset(pc->data, 0, sizeof(pc->data)); }
首先,我们防止传过来指针是空指针所以使用assert函数,之后给sz记录当前联系人数为0(因为还没有添加联系人,当然就为0),之后我们在之前了解过memset函数,是一个填充函数,我们能通过该函数把data成员里面的元素全部赋值为0。
顺便来介绍一下memset函数的使用:
memset 是 C/C++ 语言中的一个库函数,用于将一段内存区域的内容设置为指定的值。
memset 函数的声明如下:
void* memset(void* ptr, int value, size_t num);
参数解释如下:
ptr:指向要被设置的内存区域的起始地址的指针。
value:要设置的值,以 int 类型表示。
num:要设置的字节数,即要设置的内存区域的大小。
memset 函数的工作原理是将指定的值 value 复制到由 ptr 所指向的内存区域的前 num 个字节中。
之后我们来调试一下,看一下是否初始化成功。
这是代码走到这里的监视窗口,可以看到里面存放的值都是随机的。
代码执行过初始化函数后,我们来查看data成员元素,发现已经成功初始化了。
ADDContact函数(添加)
我们已经初始化成功,那么我们接下来,来实现添加联系人函数的功能。
void ADDContact(Contact* pc) { assert(pc);//防止传入指针为空 if (pc->sz == MAX)//若通讯录已满直接退出该函数 { printf("通讯录已满,无法增加\n"); return; } //增加信息 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); // pc->sz++; printf("添加联系人成功!\n"); }
首先我们先来断言防止传入指针为空,之后如果通讯录已满,我们直接退出该函数。之后我们来提示输入联系人的各项数据,通过scanf函数,将数据存放到data中的各项定义变量。因为通过sz来记录联系人人数,所以是data[sz],但又因为只能通过传入指针pc来找到sz,所以是data[pa->sz]。这样我们就实现了添加一个联系人的各项数据,之后将通过pc找到sz来实现sz++,记录联系人人数,最后提示一下添加联系人成功。