IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言,实现通讯录功能 -> 正文阅读

[C++知识库]C语言,实现通讯录功能

拿到通讯录,大伙用它干什么呢?

无非就是存储朋友同学的信息,比如:姓名,地址,电话,性别等一系列他的消息。

今天就来实现一个可以容纳一千人的具有增加,删除,查找,修改,排序,展示,退出等功能的通讯录。

写代码要有逻辑,依靠目的和功能去写代码。首先明确为什么写这行代码,然后再怎么去实现它。

主函数的逻辑

先看主函数,一系列的模块功能,用函数去封装,先不考虑这些函数怎么实现,就看逻辑和过程,想实现一个上述功能的通讯录,这些函数是必不可少的吧,每一步的安排对应每一项功能。

主函数也就几十行的代码,语句都非常简单,整体逻辑框架构思好,只需要往里面添砖加瓦就行,逐步实现每一步的函数,即可。

?OK,主函数敲定后,要解决每一步的函数,尽量不要都放在主函数里面,因为那样会非常乱。。这样把他们放在另一个.C文件里面,单独是存放函数。然后函数声明以及结构体的定义和宏定义,放在单独的一个头文件.h里面。

头文件里面的各种声明

其实,也简单,只要主函数里面用到的函数,都需要声明一下,就在这个头文件里面声明,一一对应即可。后面将介绍前面两个结构体的作用。

?结构体的定义

?这是放在头文件.h里面的代码,一系列的宏定义,以后想改数字,方便。以及人的信息,用结构体定义人的信息。并且用了别名,使后续结构体使用起来方便。结构体内包含:姓名,年龄,性别,电话,地址。其中除了年龄是整型,其余全是字符数组。

还有一个结构体是通讯录的,里面放的是人的信息的结构体,这属于结构体的嵌套定义,并且因为要容纳一千人,所以用的是结构体数组,用来存放人的信息。另外,定义一个整型count用来记录当前通讯录中实际人的个数。并且也是用了别名,这样方便后面的使用。

各模块函数的实现

1,初始化通讯录的函数

不需要返回值,所以用void,传参用的是通讯录的指针也就是结构体指针,因为后续肯定要修改里面的信息。用地址传值最为合理。

基本上是传指针的函数,第一步都需要进行断言,防止指针没有意义,这是必备一步,不止这个函数,其余任何地方,任何函数,只要是传的指针,都需要,大伙一定要养成这个习惯啊。

然后将定义的记录的数count初始化为0,然后用memset库函数把通讯录结构体里面的,存放人的信息结构体数组data初始化为0。

?2,添加联系人的函数

断言部分就不用说了。

先判断数量是否以及达到最大值Max,也就是1000,之前宏定义时说过。达到最大值则不能添加了。

没有达到,则进行添加步骤,一系列的输入信息,最后一定要记住count++,在结构体数组里面,往后推一个元素。

大伙很疑惑,count的作用?就是在这里体现出来的,往后推下一个数组的元素,用count即可。类比普通数组? *p是第一个元素,之后是*(p+1),*(p+2)等等。count++就可以达到效果。

?3,删除联系人的函数

当我们想删除一个成员的时候,先输入我们要删除的成员某一个信息,比如姓名,然后再拿输入的这个信息来和通讯录里已存的信息来比较,当找到这条信息之后再进行删除操作。

在删除之前我们要先进行一次查找已有信息的操作,后面的查找是不是也要查找一个人的信息,而修改也要查找一个人的信息。

但是怎么找到想删除的成员呢?

也就是说这个查找功能好几个函数都要用到,于是我们把这个查找功能封装在实现函数的文件内部,这个函数不需要向外部声明,因为仅仅只是在通讯录源文件内部使用。加上static修饰就行了
先看,查找的函数

传值传个结构体指针是必须的,然后传一个名字,才知道查找的对象信息。然后循环遍历所有联系人的名字信息,用库函数strcmp去比较,找到的时候,返回那个元素的下标 i。*(p+i)就是那个联系人的信息了。找不到就返回-1,-1本来就是不存在的。

注释也写了,加上static的作用。

接下来看,删除的函数

首先我们要判断通讯录中是否有成员,如果没有成员,那么也就没有必要查找元素删除了。

判断有成员之后,我们先输入要删除成员的名字,然后调用查找函数找到这个成员并且返回它的下标,如果没找到就提示没找到,如果找到了我们就来进行删除操作。

这里的变量pos是所找到成员的下标,然后通过一个循环来进行成员覆盖。这里我们来判断一下循环次数,假如按照我上面举的例子,12345,要删除3,返回下标是pos = 2,而我们要覆盖的次数是3次,这里我们知道通讯录的成员个数是sz,所以sz-pos-1就是我们要循环的次数了。定义初始变量为pos,判断语句为sz-1,正好循环sz-pos-1次。

删除操作就是结构体的赋值,把后一个下标元素的值,覆盖到前一个下标元素上面。

删除完之后记得要给成员数sz减1,否则最后一个成员的内容还在那放着。

?4,查找功能的函数

这个实现,肯定简单,因为前面已经实现好一个查找函数了,拿过来直接用即可,只需要稍微加一些修饰。只要找到了,就打印出来具体的信息。

?5,展示功能的函数

展示函数接收的参数和返回类型和增加函数是一样的。

打印通讯录内容之前我们先打印一个表头,目的是方便查找。打印的时候我们可以估算一下各个信息的长度,然后打印

由于通讯录中可能有多条信息,所以打印的时候采用一个循环来打印,打印的次数就是有效信息数sz的值。打印的方法使用的是结构体基础知识,结构体成员的访问,这里就不再多提了。

?

6,修改功能的函数

修改开始前和删除是一样的,首先要找到修改的元素,这里使用的还是前面所写的查找函数,判断它的返回值。找到下标之后进行修改。修改就得重新输入信息。一系列的输入

7 ,排序功能的函数

? ? ? ? 排序同样,我们要根据成员的某一个信息来排序,可以按照名字来排序,也可以按照年龄来排序等等,这里还是使用姓名来排序。我们这里用升序排列。

字符串大小的比较就是使用库函数qsort,这是专门的排序函数如果对qsort库函数不熟悉的好兄弟,我前面有篇博客,写的就是qsort函数,模拟实现qsort。其中调用了库函数strcmp比较的是这些字符串的ASCII码值。第一个大于第二个字符串返回大于0的数,小于返回小于0的数,等于返回0。

?ok,这样一个通讯录就能实现了,看一看实际效果,每个功能都能实现

?其实这样实现,还有一些缺陷,要是有一万个人,怎么办?

其实以后要是用到动态内存管理,就可以解决这种问题了。

下面把全部代码都奉上各位老爷。。

contact.h

?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");
		return ;
	}
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->count].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->count].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->count].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->count].addr);
	pc->count++;
	printf("增加成功\n");
}

void ShowContact(const Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%20s\t%3d\t%5s\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);
	}

}

static int FindByName(Contact* pc, char name[])  //加上static修饰,只能在这个.c文件内部使用
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void DelContact(Contact* pc)
{
	assert(pc);
	int i = 0;
	char name[Max_NAME] = { 0 };
	if (pc->count == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	                    //查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要删除的人不存在\n");
		return;
	}
	                   //删除
	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 };
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	//查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	//打印
	else
	{
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	printf("%20s\t%3d\t%5s\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);
	assert(pc);
	char name[Max_NAME] = { 0 };
	printf("请输入要修改人的名字:>");
	scanf("%s", name);
	//查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
		return;
	}
	//修改
	printf("要修改人的信息已经查找到,接下来开始修改\n");
	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 com_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), com_peo_by_name);
	printf("排序成功\n");	
}

主函数部分

#define _CRT_SECURE_NO_WARNINGS 1

#include"contact.h"
void menu()            //模拟菜单,  显得专业
{
	printf("**********************************\n");
	printf("***   1. add          2.del     **\n");
	printf("***   3.search        4.modift  **\n");
	printf("***   5.show          6.sort    **\n");
	printf("***   0.exit                    **\n");
	printf("**********************************\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:
			SearchContact(&con);  //查找联系人的函数
		    break;
		case 4:
			ModifyContact(&con);  //修改联系人函数
			break;
		case 5:
			ShowContact(&con);   //展示联系人的函数
			break;
		case 6:
			SortContact(&con);   //排序的函数
			break;
		case 0:
			printf("退出通讯录\n"); 
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 18:34:21  更:2022-07-20 18:38:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:44:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码