【C语言】通讯录的实现(详解)

news2024/9/23 17:17:02

通讯录的实现


主要用到的知识:
1.结构体相关知识
2.枚举
3.多文件

在学习完结构体和枚举后就可以利用学过的知识去实现一个通讯录了

1.通讯录要求

用C语言所学知识实现下面这样一个通讯录
1.通讯录100个联系人
2.姓名
性别
年龄
电话
地址
3.添加联系人
4.删除指定联系人
5.修改指定联系人
6.查找指定联系人
7.进行排序
8.向用户展示

2.功能实现

在学习过前面扫雷游戏后,很容易理解创建多个文件去实现功能
这里建立三个文件实现不同的功能

test.c 测试主逻辑
contact.c 函数功能实现
contact.h 函数和数据声明

1.实现主逻辑

void menu()
{
	printf("**************************\n");
	printf("**********通讯录**********\n");
	printf("****1.add*******2.del*****\n");
	printf("****3.show**4.search******\n");
	printf("****5.modify***************\n");
	printf("****6.sort****0.exit******\n");
	printf("**************************\n");
	
}
int main()
{
	int input = 0;
	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 0:
			printf("退出通讯录\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;

		}

	} while (input);
	return 0;
}

这里会发现在case后边只是单纯的使用阿拉伯数字,并不会让我们更方便的直到在这个条件下将要实现的功能,因此我们可以用一下枚举

enum choose
{
	EXIT,
	ADD,
	DEL,
	SHOW,
	SEARCH,
	MODIFY,
	SORT,
};

这样我们就可以很清晰的知道所对应的功能了

2.接下来创建一个结构体类型来存放联系人的信息

考虑到这个结构体类型会被应用到各个文件中,因此我们可以将它放在头文件中

#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 10
#define MAX_ADDR 10
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;

在这段代码中,创建一个结构体类型,struct PeoInfo,并给出所包含的内容

同时这里对所需数据进行声明

在这里,使用typedef对结构体类型进行重命名为PeoInfo,方便后续使用

3.存放联系人信息

由于后续我们要对保存的联系人进行一系列操作,就需要知道其所在的位置,即需要空间来存放联系人

同时我们对有效的联系人个数进行记录,毕竟我们规定的联系人个数是有限的

当我们再在test.c,contact.c文件中使用contact.h中的常量,头文件和结构体类型时需要在在这两个文件中添加头文件

#include"contact.h"

这里可以在创建一个结构体类型

#define MAX 100
typedef struct Contact
{
	PeoInfo data[MAX] ;
	int count;

}Contact;

创建一个此类型的变量,并进行初始化

Contact con;

InitContact(&con);

在test.c文件中进行函数实现,在test.h文件中进行函数声明

函数实现
void InitContact(Contact* con)
{
	memset(con->data, 0, sizeof(con->data));
	con->count = 0;
}

这里不能直接把con->data直接赋值为0,因为con指针指向的data是数组名,是地址,不能直接把地址赋值为0

因此这里我们使用memset函数对数组data进行初始化

函数声明
//初始化
void InitContact(Contact* con);

4.进行各种功能的实现

1.Contact_Add的实现

函数实现
void Contact_Add(Contact* con)
{
	if (con->count == MAX)
	{
		printf("联系人已满,无法再添加联系人\n");
		return;
	}
	printf("请输入姓名:");
	scanf("%s", con->data[con->count].name);//找到data数组相应下标对应的空间
	//这里的name是数组名,是地址不用取地址
	printf("请输入性别:");
	scanf("%s", con->data[con->count].sex );
	printf("请输入年龄:");
	scanf("%d",&( con->data[con->count].age) );
	printf("请输入电话:");
	scanf("%s", con->data[con->count].tele );
	printf("请输入地址:");
	scanf("%s", con->data[con->count].addr );
	con->count++;
	printf("添加完成\n");
}
函数声明
//添加联系人
void Contact_Add(Contact* con);

2.Contact_Show的实现

函数实现
void Contact_Show(Contact* con)
//展现通讯录,不能改变数据,用const修饰con指针指向的数组内容
{
	int i = 0;
	printf("%-10s %-5s %-4s %-10s %-10s\n", "姓名", "性别", "年龄", "电话", "地址");
	//限制输出间距,同时使其左对齐
	for (i = 0; i < con->count; i++)
	{
		printf("%-10s %-5s %-4d %-10s %-10s\n",
			con->data[i].name,
			con->data[i].sex,
			con->data[i].age,
			con->data[i].tele,
			con->data[i].addr);
	}

}
函数声明
//展现联系人
void Contact_Show(Contact* con);

3.Contact_Del的实现

函数实现
void Contact_Del(Contact* con)
{
	if (con->count == 0)
	{
		printf("通讯录为空,没有联系人\n");
		return;
	}
	else
	{
		char name[MAX_NAME] = { 0 };
		printf("请输入你要删除人的名字\n");
		scanf("%s", name);
		int flag = My_Find(con, name);//记录下要删除的指定联系人在数组data中的位置
		if (flag == -1)
		{
			printf("不存在这个人\n");
			return;
		}
		else
		{
			int i = 0;
			for (i = flag; i < con->count-1; i++)
			{
				con->data[i] = con->data[i + 1];//从标记位置开始,让后面人的信息覆盖掉前边的
			}
			con->count--;
			printf("删除成功\n");
		}

	}
}

在这段代码中存在一个查找通讯录是否有指定联系人的函数,我们把它单独写出来

static int My_Find(Contact* con, char name[])
{
	int i = 0;
	for (i = 0; i < con->count; i++)
	{
		if(0==strcmp(con->data[i].name, name))
		return i;
	}
	return -1;//数组的下标不可能为负数
}

因为后面的查找和修改指定联系人都会用到先查找通讯录此人是否存在的函数

通过strcmp函数来判断所输入的名字与通讯录内原有的名字是否相同,如果相同返回通讯录内这个联系人所对应的下标给flag

这里的return-1,最好是不使用else语句,再循环结束时直接返回特定值,不必要在用else语句进行判读,提高了代码性能

函数声明
//删除联系人
void Contact_Del(Contact* con);

4.Contact_Search的实现

这个函数的实现比较简单

函数实现
void Contact_Search(Contact* con)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入你要查找的人的姓名\n");
	scanf("%s", name);
	int flag = My_Find(con, name);
	if (flag == -1)
	{
		printf("通讯录内没有这个人\n");
		return;
	}
	printf("%-10s %-5s %-4s %-10s %-10s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%-10s %-5s %-4d %-10s %-10s\n",
		con->data[flag].name,
		con->data[flag].sex,
		con->data[flag].age,
		con->data[flag].tele,
		con->data[flag].addr);

	
		
	
}

```c
函数声明
//查找指定联系人
void Contact_Search(Contact* con);

5.Contact_Modify的实现

修改联系人函数实现步骤
1.用户输入需要修改的联系人
2.通过查找函数找到该联系人所在位置
3.对该联系人信息进行修改

函数实现
void Contact_Modify(Contact* con)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入你要修改的人的姓名\n");
	scanf("%s", name);
	int flag = My_Find(con, name);
	if (flag == -1)
	{
		printf("通讯录内没有这个人\n");
		return;
	}
	else
	{
		printf("请输入姓名:");
		scanf("%s", con->data[flag].name);
		printf("请输入性别:");
		scanf("%s", con->data[flag].sex);
		printf("请输入年龄:");
		scanf("%d", &(con->data[flag].age));
		printf("请输入电话:");
		scanf("%s", con->data[flag].tele);
		printf("请输入地址:");
		scanf("%s", con->data[flag].addr);

		printf("修改成功\n");
	}
}

在修改这一块,我们找到要修改的联系人的位置,直接在相应位置进行修改,对原数据进行覆盖即可

函数声明
//修改指定联系人
void Contact_Modify(Contact* con);

6.Contact_Sort得实现

对联系人进行排序,可以根据多种规定的排序规则进行排序,这里就使用姓名对其进行排序

这里直接使用qsort快速排序

在这里插入图片描述
在cplusplus网站上搜索出来qsort的函数声明,以及它的头文件
#include<stdlib.h>

#include<stdlib.h>
函数实现
int Com_Name(Contact* e1, Contact* e2)
{
	return strcmp(((PeoInfo*)e1)->name,((PeoInfo*)e2)->name);//比较函数
}
void Contact_Sort(Contact* con)
{
	qsort(con->data, con->count, sizeof(PeoInfo), Com_Name);
	printf("排序成功\n");
}

这里在比较函数中,我们先把e1,e2强制转换成PeoInfo指针类型,再找到所对应的内容name,使用strcmp函数进行比较,

函数声明
//排序联系人
void Contact_Sort(Contact* con);

就此,在控制台实现的通讯录就完成了

下面附源码

contact.h

# define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 10
#define MAX_ADDR 10
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;
#define MAX 100
typedef struct Contact
{
	PeoInfo data[MAX] ;
	int count;

}Contact;

//初始化
void InitContact(const Contact* con);
//添加联系人
void Contact_Add(Contact* con);
//展现联系人
void Contact_Show(Contact* con);
//删除联系人
void Contact_Del(Contact* con);
//查找指定联系人
void Contact_Search(Contact* con);
//修改指定联系人
void Contact_Modify(Contact* con);
//排序联系人
void Contact_Sort(Contact* con);

contact.c

# define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
void InitContact(Contact* con)
{
	memset(con->data, 0, sizeof(con->data));
	con->count = 0;
}

void Contact_Add(Contact* con)
{
	if (con->count == MAX)
	{
		printf("联系人已满,无法再添加联系人\n");
		return;
	}
	else
	{
		printf("请输入姓名:");
		scanf("%s", con->data[con->count].name);//找到data数组相应下标对应的空间
		//name是数组名,是地址,不用再取地址了
		printf("请输入性别:");
		scanf("%s", con->data[con->count].sex);
		printf("请输入年龄:");
		scanf("%d", &(con->data[con->count].age));
		printf("请输入电话:");
		scanf("%s", con->data[con->count].tele);
		printf("请输入地址:");
		scanf("%s", con->data[con->count].addr);
		con->count++;
		printf("添加完成\n");
	}
}

void Contact_Show(Contact* con)
//展现通讯录,不能改变数据,用const修饰con指针指向的数组内容
{
	int i = 0;
	printf("%-10s %-5s %-4s %-10s %-10s\n", "姓名", "性别", "年龄", "电话", "地址");
	//限制输出间距,同时使其左对齐
	for (i = 0; i < con->count; i++)
	{
		printf("%-10s %-5s %-4d %-10s %-10s\n",
			con->data[i].name,
			con->data[i].sex,
			con->data[i].age,
			con->data[i].tele,
			con->data[i].addr);
	}

}


static int My_Find(Contact* con, char name[])
{
	int i = 0;
	for (i = 0; i < con->count; i++)
	{
		if(0==strcmp(con->data[i].name, name))
		return i;
	}
	return -1;//数组的下标不可能为负数
}

void Contact_Del(Contact* con)
{
	if (con->count == 0)
	{
		printf("通讯录为空,没有联系人\n");
		return;
	}
	else
	{
		char name[MAX_NAME] = { 0 };
		printf("请输入你要删除人的名字\n");
		scanf("%s", name);
		int flag = My_Find(con, name);
		if (flag == -1)
		{
			printf("不存在这个人\n");
			return;
		}
		else
		{
			int i = 0;
			for (i = flag; i < con->count-1; i++)
			{
				con->data[i] = con->data[i + 1];
			}
			con->count--;
			printf("删除成功\n");
		}

	}
}


void Contact_Search(Contact* con)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入你要查找的人的姓名\n");
	scanf("%s", name);
	int flag = My_Find(con, name);
	if (flag == -1)
	{
		printf("通讯录内没有这个人\n");
		return;
	}
	printf("%-10s %-5s %-4s %-10s %-10s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%-10s %-5s %-4d %-10s %-10s\n",
		con->data[flag].name,
		con->data[flag].sex,
		con->data[flag].age,
		con->data[flag].tele,
		con->data[flag].addr);

}

void Contact_Modify(Contact* con)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入你要修改的人的姓名\n");
	scanf("%s", name);
	int flag = My_Find(con, name);
	if (flag == -1)
	{
		printf("通讯录内没有这个人\n");
		return;
	}
	else
	{
		printf("请输入姓名:");
		scanf("%s", con->data[flag].name);
		printf("请输入性别:");
		scanf("%s", con->data[flag].sex);
		printf("请输入年龄:");
		scanf("%d", &(con->data[flag].age));
		printf("请输入电话:");
		scanf("%s", con->data[flag].tele);
		printf("请输入地址:");
		scanf("%s", con->data[flag].addr);

		printf("修改成功\n");
	}
}
//void qsort(void* base, size_t num, size_t size,元素中每个元素的大小字节
//	int (*compar)(const void*, const void*));
int Com_Name(Contact* e1, Contact* e2)
{
	return strcmp(((PeoInfo*)e1)->name,((PeoInfo*)e2)->name);//比较函数
}
void Contact_Sort(Contact* con)
{
	qsort(con->data, con->count, sizeof(PeoInfo), Com_Name);
	printf("排序成功\n");
}

test.c

# define _CRT_SECURE_NO_WARNINGS 1

#include"contact.h"
void menu()
{
	printf("**************************\n");
	printf("**********通讯录**********\n");
	printf("****1.add*******2.del*****\n");
	printf("****3.show**4.search******\n");
	printf("****5.modify***************\n");
	printf("****6.sort****0.exit******\n");
	printf("**************************\n");
	
}
enum choose
{
	EXIT,
	ADD,
	DEL,
	SHOW,
	SEARCH,
	MODIFY,
	SORT,
};
int main()
{
	Contact con;
	InitContact(&con);
	int input = 0;
	do 
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			Contact_Add(&con);
			break;
		case DEL:
			Contact_Del(&con);
			break;
		case SHOW:
			Contact_Show(&con);
			break;
		case SEARCH:
			Contact_Search(&con);
			break;
		case MODIFY:
			Contact_Modify(&con);
			break;
		case SORT:
			Contact_Sort(&con);
			break;
		case 0:
			printf("退出通讯录\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;

		}

	} while (input);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2099802.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL server数据库实现远程跨服务器定时同步传输数据

项目背景 公司新建项目&#xff0c;需要访问生产数据&#xff0c;但是规定不能直接访问生产数据库服务器&#xff0c;所以得考虑通过中间库的形式实现。经过评估项目需求 &#xff0c;以及当前拥有的环境。 需求&#xff1a; 1.用户不需要实时获取生产数据 2.用户只需要指定的…

Python青少年简明教程:函数

Python青少年简明教程&#xff1a;函数 在Python中&#xff0c;函数是一段可重用的代码块&#xff0c;用于执行特定的任务。函数能够接受输入参数&#xff0c;执行特定的操作&#xff0c;并返回结果。 Python提供了许多内置函数&#xff0c;如print()、len()、eval()等&#x…

Java基于微信小程序的校园兼职小程序

博主介绍&#xff1a;✌stormjun、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…

shadertoy-sdf 操作

vec3 col getBackgroundColor(uv); float d1 sdCircle(uv, 0.1, vec2(0., 0.)); float d2 sdSquare(uv, 0.1, vec2(0.15, 0));float res; // result1、union res min(d1, d2); // union2、intersection res max(d1, d2); // intersection3、subtraction res max(-d1, d…

Python实战案例数据合并订单表和商品价格表数据

有如下数据&#xff0c;订单表和商品价格表&#xff0c;进行数据合并&#xff0c;输出客户需要的效果。 数据样例&#xff1a;&#x1f447; 订单表: 商品价格表: 最终效果&#xff1a; 01实现思路 目的是将订单数据和商品价格数据按照商品id和时间进行匹配&#xff0c;以…

基于nodejs+vue+uniapp的学习资料销售平台小程序

开发语言&#xff1a;Nodejs框架&#xff1a;expressuniapp数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;VS Code 系统展示 管理员登录 管理员主界面 用户管理 学习资料管理 订单管理 系统管理 用户…

未来已来:2024年远程控制行业的新星工具推荐

个人用户对于设备管理的便捷需求&#xff0c;远程控制软件都以其独特的优势&#xff0c;搭建起一座座沟通的桥梁。今天&#xff0c;我们就来探索一款集高效性、安全性与易用性于一体的远程控制软件。为了软件得到的方便我会介绍比如能从向日葵远程控制官网、TD官网、GH官网能直…

用RPC Performance Inspector 优化你的区块链

目录 什么是RPC&#xff1f; RPC Performance Inspector 是做什么的&#xff1f; 为什么需要这个工具&#xff1f; 如何使用它&#xff1f; 适合谁用&#xff1f; 如何使用&#xff1f; 什么是RPC&#xff1f; RPC Performance Inspector 是一个专门用于测试和分析RPC性能…

C语言 动态内存管理 #动态内存函数的介绍 #常见的动态内存错误 #C\C++ 程序的内存开辟 #柔性数组

文章目录 前言 一、为什么存在动态内存分配 二、动态内存函数的介绍 1、malloc 2、free 3、calloc 4、realloc realloc 的工作原理&#xff1a; 三、常见的动态内存错误 1、对NULL指针的解引用操作 2、对动态开辟空间的越界访问 3、对非动态开辟的空间使用 free 来释…

数学建模强化宝典(8)粒子群算法

前言 粒子群算法&#xff08;Particle Swarm Optimization, PSO&#xff09;是一种基于群体智能的优化算法&#xff0c;它源于对鸟群捕食行为的研究。通过模拟鸟群中的个体相互协作和信息共享来寻找最优解&#xff0c;粒子群算法已被广泛应用于函数优化、神经网络训练、模糊系统…

跨地域工作利器:深度解析2024年远程控制软件的新特性

无论是跨地域的团队协作、技术支持&#xff0c;使用远程控制工具可以让距离不再是障碍。这次我介绍一些可以直接下载使用的远程工具&#xff0c;比如从向日葵远程控制官网&#xff0c;EV官网、TV官网等就能直接下载使用的工具。 1.向日葵远程控制 链接直通车&#xff1a;http…

微服务--Nacos

一、Nacos简介 Nacos&#xff08;Naming and Configuration Service&#xff09;是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它致力于帮助开发者快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos支持几乎所有主流类型的服…

惠中科技智能高效综合光伏清洗技术

惠中科技综合光伏清洗技术&#xff1a;&#xff0c;引领绿色清洁新时代 随着全球对可再生能源需求的不断增长&#xff0c;光伏产业作为绿色能源的重要组成部分&#xff0c;正迎来前所未有的发展机遇。然而&#xff0c;光伏电站的广泛应用也带来了光伏板清洁维护的挑战。灰尘、…

SprinBoot+Vue问卷调查微信小程序的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue3.6 uniapp代码 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平…

AI耳机是不是好赛道

AI耳机是不是好赛道&#xff1f; 数科星球原创 作者丨苑晶 编辑丨大兔 AI硬件方兴未艾&#xff0c;行业里出现了新变化。 最近&#xff0c;AI耳机开始受到关注。有人将其看作可堪比无线蓝牙耳机革命的大时代&#xff0c;也有人认为其鸡肋无比、并不看好。询问了多家投资机…

Pr:项目设置 - 颜色

Pr菜单&#xff1a;文件/项目设置 File/Project Settings “项目设置”对话框中的颜色 Color选项卡主要用于管理项目的色彩空间和显示设置&#xff0c;确保在不同设备和环境下色彩显示的一致性和准确性&#xff0c;特别是处理 HDR 或对数格式的视频素材时。 颜色设置 Color Set…

SprinBoot+Vue在线商城微信小程序的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue3.6 uniapp代码 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平…

网络攻击的类型

网络攻击的数量正在增长&#xff0c;迫切需要更强大的网络安全措施来应对这些攻击。作为程序员和 IT 专业人员&#xff0c;我们必须了解顶级组织中发生的最常见的网络攻击类型。 以下各节详细介绍了可能损害任何系统的不同类型的网络攻击。了解这些攻击对于检测和防止进一步攻…

esp32 中断最简验证程序

13脚接3.3v脚&#xff0c;显示OK &#xff0c;不能直接接5v电压脚 中断程序最好是为各种执行设置标志位。不能处理占用长时间的指令 准备利用中断对超声波模块编程 #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/…

3.4 数据传送指令

&#x1f393; 微机原理考点专栏&#xff08;通篇免费&#xff09; 欢迎来到我的微机原理专栏&#xff01;我将帮助你在最短时间内掌握微机原理的核心内容&#xff0c;为你的考研或期末考试保驾护航。 为什么选择我的视频&#xff1f; 全程考点讲解&#xff1a;每一节视频都…