C语言版通讯录操作系统

2023-10-27

        通讯录操作系统

目录

        通讯录操作系统

一.通讯录的简介      

三.各部分代码实现:

1.首先在主函数中编写项目的整体框架

2. 优化菜单界面——menu函数

3.封装属性

4.创建通讯录的结构变量(在main函数中)

5.函数声明(头文件中实现)

 6.函数实现——在Contact.c中

A.初始化通讯录

B.增加成员功能

C.显示成员功能

D.查找功能——仅用于删、改、查询功能的函数实现

        E.删除人员功能

F.修改人员属性功能

 G.查询人员功能

H.排序功能

I.统计目前通讯录中人员的总量功能

四.完整代码实现:

1.test.c:

2.Contact.h头文件代码:

3.Contact.c函数功能实现:


一.通讯录的简介      

  通讯录管理系统是一个将内部数据信息有机地组织起来,确切地记录人们地相关信息,操作方便,灵活查询。

        二.该项目的实现要求:

       1. 该项目使用C语言设计了一个简单类型的通讯录管理系统,记录通讯录内的人员姓名,年龄,电话,地址等信息属性。

        2.该项目拥有增、删、查、改、显示、排序、及统计人员等功能。

        3.删除,查询,修改三种功能需要输入联系人的姓名作为系统关键字进行处理。

        4.排序也可以实现多种方式的排序,我这里采用了姓名与年龄两种方式进行。

        5.在项目中,可以一直进行循环操作,输入0则会跳出循环,结束该程序的执行。

        6.该项目只是小型程序,只能在调试代码时记录操作后的人员信息,结束程序后就会自动销毁所有信息,之后我会优化通讯录项目,使其实现更加高效的执行效率。

三.各部分代码实现:

1.首先在主函数中编写项目的整体框架

        写程序时,一般都会用do...while语句作为循环结构进行操作。之后使用多分支switch语句,通过输入数字进行各项目功能的实现。

int main() {
	int input = 0;
	
	do {
		menu();
		printf("请输入你的选择:\n");
		scanf("%d", &input);
		switch (input) {
		case 1:
			AddContact();
			break;
		case 2:
			DelContact();
			break;
		case 3:
			ModifyContact();
			break;
		case 4:
			SearchContact();
			break;
		case 5:
			ShowContact();
			break;
		case 6:
			qsortContact();
			break;
		case 7:
			TotalContact();
			break;
		case 0:
			printf("即将退出程序\n");
			break;
		default:
			printf("输入错误!请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

2. 优化菜单界面——menu函数

void menu() {
	printf("************通讯录管理界面**************\n");
	printf("****************1.Add.*****************\n");
	printf("****************2.Del.*****************\n");
	printf("****************3.Mod.*****************\n");
	printf("****************4.Search.**************\n");
	printf("****************5.Show.****************\n");
	printf("****************6.Qsort.***************\n");
	printf("****************7.Total.***************\n");
	printf("****************0.Exit.****************\n");
}

         通过多个*号美化菜单界面,给用户一种舒适感觉。


3.封装属性


#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TALE 12
#define MAX_ADDR 20

//人的结构体
typedef struct PeoInf {
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tale[MAX_TALE];
	char addr[MAX_ADDR];
}PeoInf;


//通讯录的结构体(嵌套)
typedef struct Contact {
	PeoInf peo[MAX];
	int count;
}Contact;

        创建项目头文件Contact.h,在头文件中使用两个结构体类型,封装成员的各个属性,另一个结构体采用嵌套形式再封装通讯录的属性。 使用typedef可以重命名结构体的名字(重命名只是嫌结构体类型名字太长)。

        使用宏定义去限制各属性的信息长度,方便修改、


4.创建通讯录的结构变量(在main函数中)

Contact con;
	//初始化通讯录
	InitContact(&con);//结构体传参——传址

        这里需要在test.c中引入与头文件Contact.h的操作:#include"Contact.h" 

        这样可以将通讯录结构体变量作为参数执行函数操作。

        注:这里采用传址调用,可以修改结构体对象,访问时需要用到" -> "


5.函数声明(头文件中实现)

//函数声明
void InitContact(Contact* pc);

void AddContact(Contact* pc);

void ShowContact(Contact* pc);

void DelContact(Contact* pc);

void ModifyContact(Contact* pc);

void SearchContact(Contact* pc);

void qsortContact(Contact* pc);

void TotalContact(Contact* pc);

        以上都是项目各个功能函数的声明!


 6.函数实现——在Contact.c中

        函数的实现需要再创建一个.c文件在其中编写代码,这是为了分类main函数的代码量。

A.初始化通讯录

void InitContact(Contact* pc) {
	memset(pc->peo, 0, sizeof(pc->peo));//初始化所有信息为0
	pc->count = 0;
}

使用memset函数可以让通讯录的peo数组成员全初始化为0。count用来统计成员个数。

         


B.增加成员功能

void AddContact(Contact* pc) {
	assert(pc);
	if (pc->count == 100) {
		printf("抱歉,通讯录已满,无法再进行添加\n");
		return;
	}
		printf("正在准备添加认证:\n");
		printf("请输入添加人的姓名:\n");
		scanf("%s", pc->peo[pc->count].name);
		printf("请输入添加人的年龄:\n");
		scanf("%d", &(pc->peo[pc->count].age));
		printf("请输入添加人的性别:\n");
		scanf("%s", pc->peo[pc->count].sex);
		printf("请输入添加人的电话:\n");
		scanf("%s", pc->peo[pc->count].tale);
		printf("请输入添加人的住址:\n");
		scanf("%s", pc->peo[pc->count].addr);
		pc->count++;
	printf("增加成功\n");
}

每增加一个成员就要使count++一次。


C.显示成员功能

//显示函数
void ShowContact(Contact* pc) {
	assert(pc);
	if (pc->count == 0) {
		printf("抱歉,通讯录为空,无法查看\n");
		return;
	}
		int i = 0;
		printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "地址");
		for (int i = 0; i <pc->count; i++) {
			printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n", pc->peo[i].name,
				pc->peo[i].age,
				pc->peo[i].sex,
				pc->peo[i].tale,
				pc->peo[i].addr);
	}
}

        '\t'字符为间隔符,数字前加-号表示左对齐,这是为了整齐规范的显示成员信息。


D.查找功能——仅用于删、改、查询功能的函数实现

static Find(Contact* pc, char name[]) {//查找函数
	int i = 0;
	for (i = 0; i < pc->count; i++) {
		if (strcmp(pc->peo[i].name, name) == 0) {
			return i;
		}
	}
		return -1;
}

        E.删除人员功能

void DelContact(Contact* pc){
		assert(pc);
		char name[MAX_NAME] = { 0 };
		if (pc->count == 0) {
			printf("抱歉,通讯录为空,无法删除\n");
			return;
		}
			printf("请输入删除人的名字:\n");
			scanf("%s", name);
			int ret = Find(pc, name);
			if (ret == -1) {
				printf("抱歉,查找的人不存在\n");
				return;
			}
			int i = 0;
			for (i = ret; i < pc->count - 1; i++) {
				pc->peo[i] = pc->peo[i + 1];
				printf("已删除该成员\n");
			}
				pc->count--;
		printf("删除成功\n");
		}

 使用成员姓名作为删除关键字,进入查找函数,先找出来,再进行删除。


F.修改人员属性功能

void ModifyContact(Contact* pc) {
		assert(pc);
		char name[MAX_NAME] = { 0 };
		if (pc->count == 0) {
			printf("抱歉,通讯录为空,无法修改\n");
			return;
		}
		printf("请输入要修改的人员名字:\n");
		scanf("%s", name);
		int ret = Find(pc, name);
		if (ret == -1) {
			printf("要查找的人不存在,无法进行修改\n");
			return;
		}
		printf("正在执行修改验证:\n");
		printf("请输入修改人的姓名:\n");
		scanf("%s", pc->peo[ret].name);
		printf("请输入修改人的年龄:\n");
		scanf("%d", &(pc->peo[ret].age));
		printf("请输入修改人的性别:\n");
		scanf("%s", pc->peo[ret].sex);
		printf("请输入修改人的电话:\n");
		scanf("%s", pc->peo[ret].tale);
		printf("请输入修改人的住址:\n");
		scanf("%s", pc->peo[ret].addr);
		printf("修改成功\n");

	}

  使用成员姓名作为查找关键字,进入查找函数,先找出来,再进行整体修改。


 G.查询人员功能

        

void SearchContact(Contact* pc) {
		char name[MAX_NAME] = { 0 };
		assert(pc);
		if (pc->count == 0) {
			printf("通讯录为空,无法查找\n");
			return;
		}
		printf("请输入要查找的人的姓名:\n");
		scanf("%s", name);
		int ret = Find(pc, name);
		if (ret == -1) {
			printf("该成员不存在,查找失败\n");
		}
		else {
			printf("查找成功,请查看以下信息\n");
			printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "地址");
			printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n", pc->peo[ret].name,
				pc->peo[ret].age,
				pc->peo[ret].sex,
				pc->peo[ret].tale,
				pc->peo[ret].addr);
		}
	}

        此功能与显示功能相似。


H.排序功能

    //按姓名排序
int cmp_by_name(const void* e1, const void* e2) {
		return strcmp(((PeoInf*)e1)->name, ((PeoInf*)e2)->name);
	}

    //按年龄排序
	int cmp_by_age(const void* e1, const void* e2) {
		return ((PeoInf*)e1)->age-((PeoInf*)e2)->age;
	}

	void qsortContact(Contact* pc) {
		assert(pc);
		int i = 0;
		printf("该程序有两种排序方式:\n");
		printf("1.按年龄排序        2.按姓名排序\n");
		printf("请输入你想进行排序标准的序号:\n");
		scanf("%d", &i);
		if (i == 1) {
			qsort(pc->peo, pc->count, sizeof(PeoInf), cmp_by_age);
			printf("通讯录已按年龄排序成功");
		}
		if (i == 2) {
			qsort(pc->peo, pc->count, sizeof(PeoInf), cmp_by_name);
			printf("通讯录已按姓名排序成功\n");
		}
	}

         使用qsort排序函数进行。


I.统计目前通讯录中人员的总量功能

void TotalContact(Contact* pc) {
		assert(pc);
		if (pc->count == 0) {
			printf("通讯录为空,人员为空\n");
			return;
		}
		else {
			int total = pc->count;
			printf("目前通讯录中共有%d名联系人\n", total);
		}
	}

四.完整代码实现:

1.test.c:

#define _CRT_SECURE_NO_WARNINGS 1
# include<stdio.h>
#include"Contact.h"
void menu() {
	printf("***********通讯录管理界面**************\n");
	printf("****************1.Add.*****************\n");
	printf("****************2.Del.*****************\n");
	printf("****************3.XIU.*****************\n");
	printf("****************4.Search.**************\n");
	printf("***************5.Show.*****************\n");
	printf("****************6.Qsort.***************\n");
	printf("***************5.Total.****************\n");
	printf("***************0.Exit.*****************\n");

	}
int main() {
	int input = 0;
	Contact con;
	//初始化通讯录
	InitContact(&con);//结构体传参——传址

	do {
		menu();
		printf("请输入你的选择:\n");
		scanf("%d", &input);
		switch (input) {
		case 1:
			AddContact(&con);
			break;
		case 2:
			DelContact(&con);
			break;
		case 3:
			ModifyContact(&con);
			break;
		case 4:
			SearchContact(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 6:
			qsortContact(&con);
			break;
		case 7:
			TotalContact(&con);
			break;
		case 0:
			printf("即将退出程序\n");
			break;
		default:
			printf("输入错误!请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}


2.Contact.h头文件代码:

#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>

#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TALE 12
#define MAX_ADDR 20



//人的结构体
typedef struct PeoInf {
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tale[MAX_TALE];
	char addr[MAX_ADDR];
}PeoInf;


//通讯录的结构体(嵌套)
typedef struct Contact {
	PeoInf peo[MAX];
	int count;
}Contact;

//函数声明
void InitContact(Contact* pc);

void AddContact(Contact* pc);

void ShowContact(Contact* pc);

void DelContact(Contact* pc);

void ModifyContact(Contact* pc);

void SearchContact(Contact* pc);

void qsortContact(Contact* pc);


void TotalContact(Contact* pc);

3.Contact.c函数功能实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
//初始化
void InitContact(Contact* pc) {
	memset(pc->peo, 0, sizeof(pc->peo));//初始化所有信息为0
	pc->count = 0;
}

void AddContact(Contact* pc) {
	assert(pc);
	if (pc->count == 100) {
		printf("抱歉,通讯录已满,无法再进行添加\n");
		return;
	}
		printf("正在准备添加认证:\n");
		printf("请输入添加人的姓名:\n");
		scanf("%s", pc->peo[pc->count].name);
		printf("请输入添加人的年龄:\n");
		scanf("%d", &(pc->peo[pc->count].age));
		printf("请输入添加人的性别:\n");
		scanf("%s", pc->peo[pc->count].sex);
		printf("请输入添加人的电话:\n");
		scanf("%s", pc->peo[pc->count].tale);
		printf("请输入添加人的住址:\n");
		scanf("%s", pc->peo[pc->count].addr);
		pc->count++;
	printf("增加成功\n");
}

//显示函数
void ShowContact(Contact* pc) {
	assert(pc);
	if (pc->count == 0) {
		printf("抱歉,通讯录为空,无法查看\n");
		return;
	}
		int i = 0;
		printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "地址");
		for (int i = 0; i <pc->count; i++) {
			printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n", pc->peo[i].name,
				pc->peo[i].age,
				pc->peo[i].sex,
				pc->peo[i].tale,
				pc->peo[i].addr);
	}
}

static Find(Contact* pc, char name[]) {//查找函数
	int i = 0;
	for (i = 0; i < pc->count; i++) {
		if (strcmp(pc->peo[i].name, name) == 0) {
			return i;
		}
	}
		return -1;
}


	//删除
	void DelContact(Contact* pc){
		assert(pc);
		char name[MAX_NAME] = { 0 };
		if (pc->count == 0) {
			printf("抱歉,通讯录为空,无法删除\n");
			return;
		}
			printf("请输入删除人的名字:\n");
			scanf("%s", name);
			int ret = Find(pc, name);
			if (ret == -1) {
				printf("抱歉,查找的人不存在\n");
				return;
			}
			int i = 0;
			for (i = ret; i < pc->count - 1; i++) {
				pc->peo[i] = pc->peo[i + 1];
				printf("已删除该成员\n");
			}
				pc->count--;
		printf("删除成功\n");
		}


	void ModifyContact(Contact* pc) {
		assert(pc);
		char name[MAX_NAME] = { 0 };
		if (pc->count == 0) {
			printf("抱歉,通讯录为空,无法修改\n");
			return;
		}
		printf("请输入要修改的人员名字:\n");
		scanf("%s", name);
		int ret = Find(pc, name);
		if (ret == -1) {
			printf("要查找的人不存在,无法进行修改\n");
			return;
		}
		printf("正在执行修改验证:\n");
		printf("请输入修改人的姓名:\n");
		scanf("%s", pc->peo[ret].name);
		printf("请输入修改人的年龄:\n");
		scanf("%d", &(pc->peo[ret].age));
		printf("请输入修改人的性别:\n");
		scanf("%s", pc->peo[ret].sex);
		printf("请输入修改人的电话:\n");
		scanf("%s", pc->peo[ret].tale);
		printf("请输入修改人的住址:\n");
		scanf("%s", pc->peo[ret].addr);
		printf("修改成功\n");

	}

	void SearchContact(Contact* pc) {
		char name[MAX_NAME] = { 0 };
		assert(pc);
		if (pc->count == 0) {
			printf("通讯录为空,无法查找\n");
			return;
		}
		printf("请输入要查找的人的姓名:\n");
		scanf("%s", name);
		int ret = Find(pc, name);
		if (ret == -1) {
			printf("该成员不存在,查找失败\n");
		}
		else {
			printf("查找成功,请查看以下信息\n");
			printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "地址");
			printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n", pc->peo[ret].name,
				pc->peo[ret].age,
				pc->peo[ret].sex,
				pc->peo[ret].tale,
				pc->peo[ret].addr);
		}
	}


	int cmp_by_name(const void* e1, const void* e2) {
		return strcmp(((PeoInf*)e1)->name, ((PeoInf*)e2)->name);
	}

	int cmp_by_age(const void* e1, const void* e2) {
		return ((PeoInf*)e1)->age-((PeoInf*)e2)->age;
	}

	void qsortContact(Contact* pc) {
		assert(pc);
		int i = 0;
		printf("该程序有两种排序方式:\n");
		printf("1.按年龄排序        2.按姓名排序\n");
		printf("请输入你想进行排序标准的序号:\n");
		scanf("%d", &i);
		if (i == 1) {
			qsort(pc->peo, pc->count, sizeof(PeoInf), cmp_by_age);
			printf("通讯录已按年龄排序成功");
		}
		if (i == 2) {
			qsort(pc->peo, pc->count, sizeof(PeoInf), cmp_by_name);
			printf("通讯录已按姓名排序成功\n");
		}
	}

	void TotalContact(Contact* pc) {
		assert(pc);
		if (pc->count == 0) {
			printf("通讯录为空,人员为空\n");
			return;
		}
		else {
			int total = pc->count;
			printf("目前通讯录中共有%d名联系人\n", total);
		}
	}

好了。以上就是通讯录操作系统完整代码,下期见!        记得点一键三连哟~ 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言版通讯录操作系统 的相关文章

随机推荐

  • Android Studio 快速跳转到XML布局界面

    http www jianshu com p 8ca15b831b31 我们开发Android应用程序时 Activity或者Fragment会有一个相对应的布局 在Eclipse中或者一般的做法 我们会在Java代码中找到对应的代码 然后
  • jquery之ajax——全局事件引用方式以及各个事件(全局/局部)执行顺序

    jquery中各个事件执行顺序如下 1 ajaxStart 全局事件 2 beforeSend 局部事件 3 ajaxSend 全局事件 4 success 局部事件 5 ajaxSuccess 全局事件 6 error 局部事件 7 aj
  • Python画图示例(1) 一维数据集绘图

    Python画图示例 1 一维数据集绘图 Python画图示例 2 二维数据集绘图 Python画图示例 3 其他绘图样式 散点图 直方图等 Python画图示例 4 3D绘图 目录 1 用 Numpy ndarray 作为数据传入 ply
  • Trie 前缀树 字典树 简介+实现

    简介 最上面的是根结点 这棵树中存的单词是apple app all bat 如果IsWord为True 就说明从根节点连到这个结点的字母组成的是一个单词 使用前缀树查询的时候时间复杂度只和单词的长度相关 实现 import java ut
  • ctfshow-内部赛

    登录就有flag签退蓝瘦出题人不想跟你说话 jpg 登录就有flag 经过一番固定的注入尝试发现 1 长度限制为5 2 存在过滤且过滤的字符会有回显 能留下来的字符很少这里列出 gt lt 在排除一下 gt lt 可以只留等于号 逗号和点号
  • 多线程编程与互斥锁

    一 线程理论基础 在操作系统原理的术语中 线程是进程的一条执行路径 线程在Unix系统下 通常被称为轻量级的进程 线程虽然不是进程 但却可以看作是Unix进程的表亲 所有的线程都是在同一进程空间运行 这也意味着多条线程将共享该进程中的全部系
  • 浅谈前后端分离

    一 前端 前后端分离已成为互联网项目开发的业界标准使用方式 通过nginx tomcat的方式 也可以中间加一个nodejs 有效的进行解耦 并且前后端分离会为以后的大型分布式架构 弹性计算架构 微服务架构 多端化服务 多种客户端 例如 浏
  • ElasticSearch安装与整合

    1 wget https artifacts elastic co downloads elasticsearch elasticsearch 6 2 4 tar gz 下载es 环境要求 2 启动elasticsearch 使用 sh b
  • 1、图解Oracle Logminer配置使用

    LogMiner配置使用手册 1 Logminer简介 1 1 LogMiner介绍 Oracle LogMiner 是Oracle公司从产品8i以后提供的一个实际非常有用的分析工具 使用该工具可以轻松获得Oracle 在线 归档日志文件中
  • PostgreSQL 备份与恢复

    http www wohedb com db html doc administrator guide adm 9 backup and restore htm www wohedb com 中文数据库 第九章 备份与恢复 PostgreS
  • LeetCode题目笔记——463. 岛屿的周长,/C++

    文章目录 题目描述 题目难度 简单 方法一 迭代 代码 方法二 深度优先遍历DFS 代码 总结 题目描述 给定一个 row x col 的二维网格地图 grid 其中 grid i j 1 表示陆地 grid i j 0 表示水域 网格中的
  • 通过jr-qrcode生成二维码并下载到客户端本地(Vue)

    生成二维码 首先生成二维码图片的地址 引入jr qrcode import jrQrcode from jr qrcode 生成二维码图片的地址 生成二维码地址 getQRCodeUrl spreadUrl const QRCodeUrl
  • 修改环境变量引起的bash 出错 解决方案

    来自 http www iteye com wiki blog 1244124 打开ubuntu 发现了 bash 的出错信息 如下 上网检索了一下 发现是环境变量有错误 找了多种方法 下面的方法是有效的一种 错误信息 Command le
  • C++函数

    C 函数 函数是一组一起执行一个任务的语句 与C程序类似 每个 C 程序都至少有一个函数 即主函数 main 通过函数 还可以把一个复杂任务分解成为若干个易于解决的小任务 充分体现结构化程序设计由粗到精 逐步细化的设计思想 即将任务合理划分
  • VR开发中的人物传送——Vive-Teleporter

    这是一个易于使用的传送系统 适用于VR开发和 Unity 游戏引擎 我这里用的PicoVR一体机 这是Unity 生成的 Navigation Mesh 作为玩家可以传送到的边界 因为这个过程是捎带Unity的工作 它是稳定的 可以在大多数
  • 服务器虚拟化 —— 集群服务器 —— 分布式 —— 云服务

    一 服务器虚拟化技术 是下面集群服务器 云服务的技术基石 将服务器的物理资源抽象成逻辑资源 让一台服务器变成几台甚至上百台 很少见啊 相互隔离的虚拟服务器 我们不再受限于物理上的界限 而是让CPU 内存 磁盘 I O等硬件变成可以动态管理的
  • 顺序表,你真的知道吗[SQL]

    好看的目录 前言 一 顺序表是什么 概念及结构 二 顺序表的实现 顺序表的缺点 几道练手题 总结 前言 线性表是n个具有相同特性的数据元素的有限序列 线性表是一种在实际中广泛使用的数据结构 常见的线性表 顺序表 链表 栈 队列 字符串 线性
  • 实现弧形切角两种方式

    1 css 的 radial gradient
  • springboot服务端接口外网远程调试,并实现HTTP服务监听 - 内网穿透

    文章目录 前言 1 本地环境搭建 1 1 环境参数 1 2 搭建springboot服务项目 2 内网穿透 2 1 安装配置cpolar内网穿透 2 1 1 windows系统 2 1 2 linux系统 2 2 创建隧道映射本地端口 2
  • C语言版通讯录操作系统

    通讯录操作系统 目录 通讯录操作系统 一 通讯录的简介 三 各部分代码实现 1 首先在主函数中编写项目的整体框架 2 优化菜单界面 menu函数 3 封装属性 4 创建通讯录的结构变量 在main函数中 5 函数声明 头文件中实现 6 函数