C语言实现--通讯录管理系统+附详细代码分析过程

news2024/11/25 22:56:53

文章目录

  • 初始化通讯录
  • 实现通讯录的各种功能
      • 添加一个联系人的信息
      • 删除一个联系人的信息
      • 查询指定联系人并打印其信息
      • 修改指定联系人的信息
      • 打印通讯录中的全部信息
      • 通过名字对通讯录中的联系人进行排序
  • 通讯录完整代码示例

初始化通讯录

首先,通讯录中每个联系人的信息至少包括:姓名、年龄、性别、电话、住址。
我们可以将这些内容定义为一个结构体,因为每个联系人的信息都有这几个要素:

struct PeoInfo
{
	char name[15];
	int age;
	char sex[5];
	int tele[12];
	char address[20];
};//每一个联系人的信息内容

但是我们仔细想想,当我们要操作通讯录中联系人的信息内容时,比如增加联系人信息,这时我们需要知道通讯录中的联系人是否已经到达上限,如果达到上限就无法再添加联系人。

所以,我们可以将联系人信息和通讯录中已有联系人个数,一同放入一个结构体中,这样就避免了执行每个功能时都要相同地传入两个变量(联系人信息,已有联系人个数)。

struct Contact
{
	struct PeoInfo data[1000];//存放1000个联系人的信息
	int size;//记录当前已有联系人的个数
};

定义好变量后,我们需要将待用内存空间清理一下,并将通讯录中起始联系人个数设为0,以便使用:

//初始化通讯录
void InitContact(struct Contact* ps)
{
	memset(ps->data, 0, sizeof(ps->data));//将待用内存空间设置为0
	ps->size = 0;//设置通讯录最初只有0个元素
}

这样,一个空白的通讯录就创建好了!

实现通讯录的各种功能

添加一个联系人的信息

首先,进入该函数体我们就需要判断通讯录内联系人是否已达上限,达到上限就无法继续添加,如果未达上限,用户就可以输入待添加的联系人的信息,而我们可以通过传入的指针找到联系人信息应当存放在哪一块内存空间。
添加完成后一定要记得将size,即通讯录中联系人个数+1。

//添加一个联系人的信息
void AddContact(struct Contact* ps)
{
	if (ps->size == 1000)
	{
		printf("通讯录已满,无法添加!\n");
	}//通讯录内联系人已达上限
	else
	{
		printf("请输入姓名:>");
		scanf("%s", ps->data[ps->size].name);
		printf("请输入年龄:>");
		scanf("%d", &(ps->data[ps->size].age));
		printf("请输入性别:>");
		scanf("%s", ps->data[ps->size].sex);
		printf("请输入电话:>");
		scanf("%s", ps->data[ps->size].tele);
		printf("请输入地址:>");
		scanf("%s", ps->data[ps->size].address);
		ps->size++;//通讯录中联系人个数+1
		printf("添加成功\n");
	}
}

删除一个联系人的信息

首先,我们需要用户输入待删除联系人的名字,并在通讯录中查找是否存在该名字的联系人。(因为后面还会有此相同的操作,所以将其封装为一个函数,避免代码冗余)
如果找到了此人,我们将其信息进行删除,删除的方法有两种:
在这里插入图片描述
虽然第二种方法操作起来比较简单,移动的次数也更少,但是我们还是使用第一种方法进行“删除”,因为第二种方法会捣乱联系人的先后顺序。
添加完成后也一定要记得将size,即通讯录中联系人个数-1。

int FindByName(char name[15],const struct Contact* ps)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (strcmp(ps->data[i].name, name) == 0)
			return i;//找到了返回下标
	}
	return -1;//找不到的情况
}

//删除一个联系人的信息
void DeleteContact(struct Contact* ps)
{
	char name[15];
	printf("请输入要删除联系人的姓名:>");
	scanf("%s", name);
	//查找
	int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
	//删除
	if (pos == -1)
	{
		printf("查无此人\n");
	}
	else
	{
		int j = 0;
		for (j = pos; j < ps->size - 1; j++)
		{
			ps->data[j] = ps->data[j + 1];
		}//从要删除的联系人位置开始,后一位联系人信息覆盖前一个联系人信息
		printf("删除成功\n");
		ps->size--;//通讯录中联系人个数-1
	}
}

查询指定联系人并打印其信息

首先,我们也需要用户输入待查找联系人的名字,如果存在此人我们就将其信息打印出来。

//查找指定联系人并打印其信息
void SreachContact(const struct Contact* ps)
{
	char name[15];
	printf("请输入要查找联系人的姓名:>");
	scanf("%s", name);
	int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
	if (pos == -1)
	{
		printf("查无此人\n");
	}
	else
	{
		printf("%-15s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");
		printf("%-15s\t%-4d\t%-5s\t%-12s\t%-20s\n",
			ps->data[pos].name,
			ps->data[pos].age,
			ps->data[pos].sex,
			ps->data[pos].tele,
			ps->data[pos].address);
	}//打印该联系人的信息内容
}

修改指定联系人的信息

要修改联系人信息自然也要先在通讯录中找到该联系人,如果找到了,我们就将该联系人信息重新录入一次就行了。

//修改指定联系人的信息
void ModifyContact(struct Contact* ps)
{
	char name[15];
	printf("请输入要修改的联系人的姓名:>");
	scanf("%s", name);
	int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
	if (pos == -1)
	{
		printf("查无此人\n");
	}
	else
	{
		printf("请输入姓名:>");
		scanf("%s", ps->data[pos].name);
		printf("请输入年龄:>");
		scanf("%d", &(ps->data[pos].age));
		printf("请输入性别:>");
		scanf("%s", ps->data[pos].sex);
		printf("请输入电话:>");
		scanf("%s", ps->data[pos].tele);
		printf("请输入地址:>");
		scanf("%s", ps->data[pos].address);
		printf("修改成功\n");
	}//修改联系人信息,即将该联系人信息重新录入
}

打印通讯录中的全部信息

首先判断通讯录是否为空(如果没有联系人,那就没有打印的必要了)。如果通讯录不为空,我们首先打印一排信息栏,接下来循环size次(即联系人个数次),打印每个联系人的信息即可。

//打印通讯录中的全部信息
void ShowContact(const struct Contact* ps)
{
	if (ps->size == 0)
	{
		printf("通讯录为空\n");
	}//通讯录中联系人个数为0
	else
	{
		printf("%-15s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");
		//打印信息栏
		int i = 0;
		for (i = 0; i < ps->size; i++)
		{
			printf("%-15s\t%-4d\t%-5s\t%-12s\t%-20s\n",
				ps->data[i].name,
				ps->data[i].age,
				ps->data[i].sex,
				ps->data[i].tele,
				ps->data[i].address);
		}//打印通讯录全部信息内容
	}
}


通过名字对通讯录中的联系人进行排序

这个排序功能我们可以借助于已有的qosrt函数进行排序,只需要写一个自定义的比较函数即可。

//自定义的比较函数
int CmpByName(const void* e1, const void* e2)
{
	return strcmp((const char*)e1, (const char*)e2);
}

//通过名字排序通讯录中联系人的先后顺序
void SortContact(struct Contact* ps)
{
	qsort(ps->data, ps->size, sizeof(struct PeoInfo), CmpByName);//排序
}

通讯录完整代码示例

实现该通讯录的代码比较多,为了能够看起来结构清晰,我们需要用3个文件将代码封装:contact.h、contact.c、test.c。

contact.h中存放函数的声明、结构体的定义以及一些库函数的头文件等。

#define _CRT_SECURE_NO_WARNINGS 1

#define MAX 1000

#define MAX_NAME 15
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDRESS 20

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

enum Option
{
	EXIT,//0
	ADD,//1
	DELETE,//2
	SREACH,//3
	MODIFY,//4
	SHOW,//5
	SORT//6
};//增加代码可读性

struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	int tele[MAX_TELE];
	char address[MAX_ADDRESS];
};//每一个联系人的信息内容

//通讯录类型
struct Contact
{
	struct PeoInfo data[MAX];//存放1000个联系人的信息
	int size;//记录当前已有联系人的个数
};

//初始化通讯录
void InitContact(struct Contact* ps);

//添加一个联系人的信息
void AddContact(struct Contact* ps);

//删除一个联系人的信息
void DeleteContact(struct Contact* ps);

//查找指定联系人并打印其信息
void SreachContact(const struct Contact* ps);

//修改指定联系人的信息
void ModifyContact(struct Contact* ps);

//打印通讯录中的全部信息
void ShowContact(const struct Contact* ps);

//通过名字排序通讯录中联系人的先后顺序
void SortContact(struct Contact* ps);

contact.c中主要就是contact.h中声明的函数的具体实现。

#include "contact.h"

//初始化通讯录
void InitContact(struct Contact* ps)
{
	memset(ps->data, 0, sizeof(ps->data));//将待用内存空间设置为0
	ps->size = 0;//设置通讯录最初只有0个元素
}

//添加一个联系人的信息
void AddContact(struct Contact* ps)
{
	if (ps->size == MAX)
	{
		printf("通讯录已满,无法添加!\n");
	}//通讯录内联系人已达上限
	else
	{
		printf("请输入姓名:>");
		scanf("%s", ps->data[ps->size].name);
		printf("请输入年龄:>");
		scanf("%d", &(ps->data[ps->size].age));
		printf("请输入性别:>");
		scanf("%s", ps->data[ps->size].sex);
		printf("请输入电话:>");
		scanf("%s", ps->data[ps->size].tele);
		printf("请输入地址:>");
		scanf("%s", ps->data[ps->size].address);
		ps->size++;//通讯录中联系人个数+1
		printf("添加成功\n");
	}
}

//通过名字查找联系人,找到了返回下标,没找到返回-1
static int FindByName(char name[MAX_NAME],const struct Contact* ps)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (strcmp(ps->data[i].name, name) == 0)
			return i;//找到了返回下标
	}
	return -1;//找不到的情况
}

//删除一个联系人的信息
void DeleteContact(struct Contact* ps)
{
	char name[MAX_NAME];
	printf("请输入要删除联系人的姓名:>");
	scanf("%s", name);
	//查找
	int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
	//删除
	if (pos == -1)
	{
		printf("查无此人\n");
	}
	else
	{
		int j = 0;
		for (j = pos; j < ps->size - 1; j++)
		{
			ps->data[j] = ps->data[j + 1];
		}//从要删除的联系人位置开始,后一位联系人信息覆盖前一个联系人信息
		printf("删除成功\n");
		ps->size--;//通讯录中联系人个数-1
	}
}

//查找指定联系人并打印其信息
void SreachContact(const struct Contact* ps)
{
	char name[MAX_NAME];
	printf("请输入要查找联系人的姓名:>");
	scanf("%s", name);
	int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
	if (pos == -1)
	{
		printf("查无此人\n");
	}
	else
	{
		printf("%-15s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");
		printf("%-15s\t%-4d\t%-5s\t%-12s\t%-20s\n",
			ps->data[pos].name,
			ps->data[pos].age,
			ps->data[pos].sex,
			ps->data[pos].tele,
			ps->data[pos].address);
	}//打印该联系人的信息内容
}

//修改指定联系人的信息
void ModifyContact(struct Contact* ps)
{
	char name[MAX_NAME];
	printf("请输入要修改的联系人的姓名:>");
	scanf("%s", name);
	int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
	if (pos == -1)
	{
		printf("查无此人\n");
	}
	else
	{
		printf("请输入姓名:>");
		scanf("%s", ps->data[pos].name);
		printf("请输入年龄:>");
		scanf("%d", &(ps->data[pos].age));
		printf("请输入性别:>");
		scanf("%s", ps->data[pos].sex);
		printf("请输入电话:>");
		scanf("%s", ps->data[pos].tele);
		printf("请输入地址:>");
		scanf("%s", ps->data[pos].address);
		printf("修改成功\n");
	}//修改联系人信息,即将该联系人信息重新录入
}

//打印通讯录中的全部信息
void ShowContact(const struct Contact* ps)
{
	if (ps->size == 0)
	{
		printf("通讯录为空\n");
	}//通讯录中联系人个数为0
	else
	{
		printf("%-15s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");
		//打印信息栏
		int i = 0;
		for (i = 0; i < ps->size; i++)
		{
			printf("%-15s\t%-4d\t%-5s\t%-12s\t%-20s\n",
				ps->data[i].name,
				ps->data[i].age,
				ps->data[i].sex,
				ps->data[i].tele,
				ps->data[i].address);
		}//打印通讯录全部信息内容
	}
}

//自定义的比较函数
int CmpByName(const void* e1, const void* e2)
{
	return strcmp((const char*)e1, (const char*)e2);
}

//通过名字排序通讯录中联系人的先后顺序
void SortContact(struct Contact* ps)
{
	qsort(ps->data, ps->size, sizeof(struct PeoInfo), CmpByName);//排序
}

test.c中就存放主函数(main函数),也就是通讯录主要的逻辑。

#include "contact.h"

void menu()
{
	printf("|-----------------------|\n");
	printf("|        contact        |\n");
	printf("|   1.Add     2.Delete  |\n");
	printf("|   3.Search  4.Modify  |\n");
	printf("|   5.Show    6.Sort    |\n");
	printf("|        0.Exit         |\n");
	printf("|-----------------------|\n");
}//打印菜单

int main()
{
	int input = 0;
	//创建通讯录
	struct Contact con;//con就是通讯录,里面包含1000个元素的数组和size
	//初始化通讯录
	InitContact(&con);
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DELETE:
			DeleteContact(&con);
			break;
		case SREACH:
			SreachContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT:
			SortContact(&con);
			break;
		case EXIT:
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

注意:
1> 运用枚举,可以增加代码的可读性,避免自己写代码以及别人阅读代码时不明确0,1,2,3,4,5,6的具体意义。
2> 用#define定义一些常用数据,如联系人个数1000,以便之后需要修改时只需修改一处,而不是修改全部用到1000的地方。

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

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

相关文章

DAY47:动态规划(十)零钱兑换Ⅱ+组合总和Ⅳ(完全背包求方案总数类型,排列+组合)

文章目录 518.零钱兑换Ⅱ&#xff08;装满背包方案数&#xff0c;本题是组合方案数&#xff09;思路DP数组含义递推公式DP数组初始化遍历顺序&#xff08;重要&#xff0c;不能颠倒&#xff09;外层物品内层背包的情况外层背包内层物品的情况完全背包求排列数和组合数 完整版总…

HTTP进化史:从HTTP1的简单到HTTP3的强大

文章目录 &#x1f4c8;I. HTTP1⚡A. 基本特点⚡B. 特点⚡C. 优缺点 &#x1f4c8;II. HTTP2⚡A. 基本特点⚡B. 特点⚡C. 优缺点 &#x1f4c8;III. HTTP3⚡A. 基本特点⚡B. 特点⚡C. 优缺点 &#x1f4c8;IV. 总结&#x1f4c8;附录&#xff1a;「简历必备」前后端实战项目&am…

资深测试整理,APP专项测试方法总结,看这篇就够了...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 APP专项测试 1、…

我们建议您关注另外两个趋势性漏洞。

即 Windows 错误报告服务 (CVE-2023-36874) 和 Windows MSHTML 平台 (CVE-2023-32046) 中的权限提升漏洞。现实生活中就有利用这两个漏洞的案例。 危险之处 要利用 CVE-2023-36874&#xff0c;攻击者需要访问目标计算机&#xff0c;并能够在普通用户默认具有有限权限的计算机上…

ESP32 LVGL:使用图标解决图片过大存不下的问题

背景 在LVGL中&#xff0c;用将图片转为C语言数组的方式储存的时候&#xff0c;图片转换的数组过大&#xff0c;当图片过多时会出现存不下的问题。 因此&#xff0c;可以使用字库图标解决该问题。 方法 将PNG图片转为字库文件 首先&#xff0c;我们将图片通过PS转为SVG矢量…

鸟类识别系统python+TensorFlow+Django网页界面+卷积网络算法+深度学习模型

一、介绍 鸟类识别系统&#xff0c;使用Python作为主要开发语言&#xff0c;基于深度学习TensorFlow框架&#xff0c;搭建卷积神经网络算法。并通过对数据集进行训练&#xff0c;最后得到一个识别精度较高的模型。并基于Django框架&#xff0c;开发网页端操作平台&#xff0c;…

XPath 的基本概念

XPath 的基本概念 引言 1. XPath 的基本概念 1.1 节点 1.2 路径表达式 1.3 轴 2. XPath 的语法和使用方法 2.1 标签定位 2.2 属性定位 2.3 文本定位 2.4 谓语和运算符 3. 示例演示 3.1 示例 1 &#xff1a; Web 自动化测试 3.2 示例 2 &#xff1a;数据提取和处理 3.3 示例 3 &…

pdsh 2.29 安装

下载&#xff1a; wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/pdsh/pdsh-2.29.tar.bz2解包&#xff1a; tar jxvf pdsh-2.29.tar.bz2 cd pdsh-2.29/安装&#xff1a; ./configure --prefix/u01/isi/pdsh-2.29/ --with-timeout6…

Spark编程-共享变量(广播变量和累加器)

共享变量是什么 Spark中的两个重要抽象一个是RDD&#xff0c;另一个就是共享变量。 在默认情况下&#xff0c;当Spark在集群的多个不同节点的多个任务上并行运行一个函数时&#xff0c;它会把函数中涉及到的每个变量&#xff0c;在每个任务上都生成一个副本。 但是&…

基于STM32 ARM+FPGA伺服控制系统总体设计方案(一)

设计需求 一套完整的伺服控制方案包括了上位机、驱控一体控制器和功率板三者。操作人员 通过上位机发送各种不同指令&#xff0c;然后控制器解析指令后执行相应的伺服功能&#xff0c;其次控 制器将驱动信号传输至功率板驱动电机&#xff0c;最后控制器采集反馈信息进行闭环…

为你带来全新的UGC体验!

当我们开始向更多 UGC 开放元宇宙&#xff0c;你们将有机会发现我们社区在 The Sandbox 中创造的一些令人惊叹的体验。 需要从你们自己的体验中获得灵感&#xff0c;或者只是想玩一些新东西&#xff1f;以下是我们的一些建造者几个月来的工作成果——现在就可以玩&#xff01; …

JVM学习

文章目录 1 JVM与Java体系结构1.0 Java发展重大事件1.1 虚拟机和Java虚拟机1.3 JVM整体结构1.4 Java代码执行流程1.5 JVM架构模型1.6 JVM的生命周期1.7 JVM发展历程 2 类加载子系统2.1 ClassLoader2.2 用户自定义类加载器2.2.1 为什么需要自定义类加载器2.2.2 自定义类加载器的…

Kong 服务和路由的添加

管理服务 这里参考DB-less-Mode&#xff0c;因为使用的是yaml配置文件的形式&#xff0c;所以所有的相关配置只需要往初始化的kong.yml文件中添加就可以了&#xff0c;就像nginx的配置文件 DB-less-Mode 创建服务 vim /etc/kong/kong.yml services: - name: my-service #…

排查思路----CPU占用过高

1、top查看cpu占用情况 %Cpu(s): 29.4 us, 24.1 sy, 0.0 ni, 10.1 id, 20.4 wa, 0.0 hi, 16.0 si, 0.0 st 发现wa和si都比较高 2、查wa高的问题 iostat -x 1 10%util 接近 100%&#xff0c;说明产生的I/O请求太多&#xff0c;I/O系统已经满负荷&#xff0c;该磁盘存在瓶颈。…

数据库性能优化中的表结构优化

数据库性能优化中的表结构优化 在数据库应用中&#xff0c;表结构的设计直接影响着数据库的性能。合理的表结构设计可以提高数据库的查询效率和性能&#xff0c;而不合理的表结构设计则可能导致查询效率低下、数据冗余、数据不一致等问题。因此&#xff0c;表结构优化是数据库…

智慧园区如何搭乘数字孪生这列快车?

无论是2022年的火爆的元宇宙还是今年出圈的ChatGPT&#xff0c;都体现着数字技术嵌入社会生活是大趋势&#xff0c;数字孪生作为智能技术的一大亮点&#xff0c;它在智慧园区中的应用会是怎样呢&#xff1f;今天我们就来聊一聊&#xff01; &#xff08;全文3000字&#xff0c;…

Star CCM+ 202206 (17.04) 详细安装步骤

首先下载win系统的安装包 阿里云盘&#xff1a; https://www.aliyundrive.com/s/WFfyvFhGxwK 提取码: x57w 百度云盘&#xff1a;https://pan.baidu.com/s/1qKgxYf2DGURCTW0rga8Xkw?pwdeiqi 提取码&#xff1a;eiqi &#xff08;资源来自网络&#xff0c;仅供个人学习交流&…

电脑提示找不到MSVCR120.dll 简单解决方法,亲测有效!

msvcr120.dll是windows系统的一部分&#xff0c;它是Windows操作系统中的一个动态链接库文件。该文件包含了一些在运行使用了C语言编写的程序时所需的函数和资源。当系统无法找到或加载msvcr120.dll文件时&#xff0c;会导致相关程序无法正常运行。 msvcr120.dll文件它提供了一…

25个高级SQL查询-基于特定排序标准对行进行排序

本专栏中的许多示例将基于以下员工表(employee)。只有少数例子将以其他表格为基础;在这些情况下,表格将与示例一起进行说明。 一、RANK 函数 RANK()函数是SQL中的窗口函数之一。窗口函数查看部分数据并计算该部分的结果。 RANK()函数根据提供的列为每一行指定一个等级…

C语言自定义类型详解(保姆级教学)

目录 1.结构体 1.1结构体的介绍 1.2结构体的声明 1.3特殊声明&#xff08;匿名结构体类型&#xff09; 1.4结构体自引用 1.5结构体变量的定义和初始化 1.6结构体内存对齐 1.7修改默认对其数 2.位段 2.1什么是位段 2.2位段的内存分配 3.枚举 3.1枚举的定义 3.2枚举…