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

news2024/11/26 5:28:09

目录

一、需要实现的功能

1.1 类型和结构体的定义

二、拆分代码

2.1 游戏菜单

2.1.1 函数调用

2.1.2 函数体的实现

2.1.2运行效果

2.2 初始化结构体

2.2.1 函数调用

2.2.2 函数体的实现

2.2.3 运行结果

2.3 添加联系人信息

2.3.1 函数调用

2.3.2 函数体的实现

2.3.3 运行结果

2.3 删除指定联系人信息

2.3.1 函数调用

2.3.2 函数体的实现

2.3.3 运行结果

2.4 查找指定联系人信息

2.4.1 函数调用

2.4.2 函数体的实现

2.4.3 运行结果

2.5 修改指定联系人信息

2.5.1 函数调用

2.5.2 函数体的实现

2.5.3 运行结果

2.6 显示所有联系人信息

2.6.1 函数调用

2.6.2 函数体的实现

2.6.3 运行结果 

2.7 以名字排序所有联系人

2.7.1 函数调用

2.7.2 函数体的实现

2.7.3 运行结果

2.8 清空所有联系人

2.8.1 函数调用

2.8.2 函数体的实现

2.8.3 运行结果

2.9 通讯录的逻辑(主函数)

三、 完整代码

3.1 contact.h(函数的声明)

3.2 contact.c(函数的实现)

3.3 test.c(测试通讯录的逻辑)

 END.


通讯录和三子棋,扫雷都是用三个模块来实现

test.c(测试通讯录的逻辑) contact.c(函数的实现) contact.h(函数的声明)

一、需要实现的功能

  • 可以添加1000个联系人信息
  • 删除指定联系人信息
  • 查找指定联系人信息
  • 修改指定联系人信息
  • 显示所有联系人信息
  • 以名字排序所有联系人
  • 清空所有联系人

1.1 类型和结构体的定义

个人信息包括:姓名,年龄,性别,电话,地址

C语言中没有能够表示个人信息的类型,需要定义结构体类型来实现

通讯录需要能够存放1000个人,可以用一个结构体数组来实现

还需要一个整型来记录存了几个人

我们可以把个人信息和记录数字的整型,组合成一个结构体,方便我们使用

定义数组大小并没有用数字直接定义,而是用宏定义实现

这样我们后期如果需要更改数组大小只需要修改一次

 

 contact,peoInfo,sz的关系

二、拆分代码

2.1 游戏菜单

2.1.1 函数调用

2.1.2 函数体的实现

 菜单就是用peintf语句实现

2.1.2运行效果

2.2 初始化结构体

结构体中的sz是记录联系人的个数,如果我们不将它初始化,他里面存放的是随机值,这样在增加联系人时+1,就没有任何意义了。

 

2.2.1 函数调用

2.2.2 函数体的实现

 

 2.2.3 运行结果

 

2.3 添加联系人信息

2.3.1 函数调用

参数是通讯录的地址也就是包含个人信息和记录个数的结构体

 

2.3.2 函数体的实现

 2.3.3 运行结果

 

2.3 删除指定联系人信息

2.3.1 函数调用

2.3.2 函数体的实现

判断姓名是否一样的函数,在查找修改中都会使用,封装成函数更加方便

 2.3.3 运行结果

2.4 查找指定联系人信息

2.4.1 函数调用

2.4.2 函数体的实现

  2.4.3 运行结果

2.5 修改指定联系人信息

2.5.1 函数调用

 

2.5.2 函数体的实现

2.5.3 运行结果

2.6 显示所有联系人信息

2.6.1 函数调用

2.6.2 函数体的实现

2.6.3 运行结果 

2.7 以名字排序所有联系人

2.7.1 函数调用

2.7.2 函数体的实现

 2.7.3 运行结果

2.8 清空所有联系人

2.8.1 函数调用

2.8.2 函数体的实现

2.8.3 运行结果

 

2.9 通讯录的逻辑(主函数)

 

 枚举的验证

 

枚举可以改变值 

 

 

三、 完整代码

3.1 contact.h(函数的声明)


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


#define NAME_MAX 20		//存放姓名的数组大小
#define SEX_MAX 6		//存放性别的数组大小
#define TELE_MAX 12		//存放电话的数组大小
#define ADDRESS_MAX 20	//存放地址的数组大小
#define DATA_MAX 1000	//存放个人信息的数组大小


enum c
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MOD,
	PRINT,
	SORT,
	EMPTY,
};

typedef struct peoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char address[ADDRESS_MAX];
}peoInfo;

//静态contact
typedef struct contact
{
	peoInfo data[DATA_MAX];//存放个人信息
	int sz;//记录有几个人的信息
}contact;





//初始化
void InitContact(contact* pc);
//增加信息
void AddContact(contact* pc);
//打印通讯录
void PrintContact(contact* pc);
//删除联系人
void DelContact(contact* pc);
//查找联系人
void SearchContact(contact* pc);
//修改联系人
void ModContact(contact* pc);
//清空联系人
void EmptyContact(contact* pc);
//联系人排序
void SortContact(contact* pc);

3.2 contact.c(函数的实现)

#include"contact.h"

//初始化
void InitContact(contact* pc)
{
	assert(pc);
	memset(pc->data, 0, sizeof(pc->data));
	pc->sz = 0;
}



//增加信息
void AddContact(contact* pc)
{
	if (pc->sz == DATA_MAX)
	{
		printf("通讯录已满,无法添加\n");
		return;
	}
	assert(pc);
	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].address);
	pc->sz++;
	printf("添加成功\n");
}



//打印通讯录
void PrintContact(contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%-10s %-5s %-6s %-12s %-15s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s %-5d %-6s %-12s %-15s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].address);
	}
	printf("\n");
	}
	
//判断名字是否一致
int Find_Name(contact* pc, char* name)
{
	assert(pc&&name);
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (0 == strcmp(pc->data[i].name, name))
		{
			return i;
		}
	}
	return -1;
}

//删除联系人
void DelContact(contact* pc)
{
	assert(pc);
	char name[NAME_MAX];
	if (pc->sz == 0)
	{
		printf("通讯录没有联系人\n");
		return;
	}
	printf("输入需要删除人的姓名\n");
	scanf("%s", name);
	//找到返回坐标,没找到返回0.
	int pos = Find_Name(pc, name);
	if (pos == -1)
	{
		printf("没有找到要删除的联系人\n");
	}
	else
	{
		int j = 0;
		for (j = pos; j <pc->sz-1; j++)
		{
			pc->data[j] = pc->data[j + 1];
		}
		pc->sz--;
		printf("删除成功\n");
		PrintContact(pc);
	}
}


//查找联系人
void SearchContact(contact* pc)
{
	assert(pc);
	char name[NAME_MAX];
	if (pc->sz == 0)
	{
		printf("通讯录没有联系人\n");
		return;
	}
	printf("输入查找人的姓名\n");
	scanf("%s", name);
	//找到返回坐标,没找到返回0.
	int pos = Find_Name(pc, name);
	if (pos == -1)
	{
		printf("没有找到要删除的联系人\n");
	}
	else
	{
		printf("找到联系人\n");
		printf("%-10s %-5s %-6s %-12s %-15s\n", "姓名", "年龄", "性别", "电话", "地址");
		printf("%-10s %-5d %-6s %-12s %-15s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex,
			pc->data[pos].tele, pc->data[pos].address);
	}
}


//修改联系人
void ModContact(contact* pc)
{
	assert(pc);
	char name[NAME_MAX];
	if (pc->sz == 0)
	{
		printf("通讯录没有联系人\n");
		return;
	}
	printf("输入需要修改联系人的姓名->");
	scanf("%s", name);
	int pos = Find_Name(pc, name);
	if (pos == -1)
	{
		printf("没有找到要删除的联系人\n");
	}
	else
	{
		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].address);
		printf("修改成功\n");
		//修改完后,打印一下子
		PrintContact(pc);
	}
}


//清空联系人
void EmptyContact(contact* pc)
{
	assert(pc);
	char q =0;
	printf("你确定要清空所有联系人吗?(Y/N)\n");
	getchar();
	scanf("%c", &q);
	if (q=='Y')
	{
		int i = 0;
		for (i = pc->sz - 1; i > 0; i--)
		{
			pc->data[i - 1] = pc->data[i];
			pc->sz--;
		}
		if (pc->sz == 1)
		{
			pc->sz--;
		}
		//打印
		printf("清空联系人\n");
		PrintContact(pc);
	}
	else
	{
		printf("取消清空联系人\n");
		return;
	}
	
}

//qsort排序
int con_name(const void* e1, const void* e2)
{
	return (strcmp(((contact*)e1)->data->name , ((contact*)e2)->data->name));
}

//联系人排序
void SortContact(contact* pc)
{
	assert(pc);
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), con_name);
	//打印
	printf("排序完成\n");
	PrintContact(pc);

}


3.3 test.c(测试通讯录的逻辑)

#include"contact.h"

void menu()
{
	printf("-------------------------------\n");
	printf("-------1.add     2.del---------\n");
	printf("-------------------------------\n");
	printf("-------3.search  4.mod---------\n");
	printf("-------------------------------\n");
	printf("-------5.print   6.sort--------\n");
	printf("-------------------------------\n");
	printf("-------7.empty   0.exit--------\n");
	printf("-------------------------------\n");

}


void test()
{
	int input = 0;
	contact con;
	InitContact(&con);
	do
	{
		menu();//菜单
		printf("选择功能->");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			//增加信息
			AddContact(&con);
			break;
		case DEL:
			//删除联系人
			DelContact(&con);
			break;
		case SEARCH:
			//查找联系人
			SearchContact(&con);
			break;
		case MOD:
			//修改联系人
			ModContact(&con);
			break;
		case PRINT:
			//打印通讯录
			PrintContact(&con);
			break;
		case SORT:
			//联系人排序
			SortContact(&con);
			break;
		case EMPTY:
			//清空联系人
			EmptyContact(&con);
			break;
		case EXIT:
			printf("退出程序。\n");
			break;
		default:
			printf("输入错误,请重新选择。\n");
			break;

		}
	} while (input);

}

int main()
{
	test();
	return 0;
}

 END.

        虽然,通讯录的功能都已经实现。但还是没有那么完美,本次能够存放1000个人的信息,但存不下1001个人的信息。只存放1个人的信息,但空间开辟了1000个,就会造成空间的极大浪费,所以还是有比较大的缺陷。

        如果空间能够动态开辟,就能完美解决这个问题,欲知后事如何,且听下回分解。


最后把这句话送给大家:

Victory won‘t come to me unless I go to it.

胜利是不会向我们走来的,我必须自己走向胜利。

 

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

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

相关文章

操作系统之光--鸿蒙

鸿蒙是什么&#xff1f;鸿蒙包含Openharmony和harmonyOS。Openharmony是华为向开放原子开源基金会捐赠了鸿蒙开源部分的代码&#xff0c;归属于开放原子开源基金会。HarmonyOS是基于Openharmony的商业发行版本。目前大家华为手机上运行就是它。鸿蒙能做什么&#xff1f;很明显&…

【算法基础】1.6 双指针算法

文章目录双指针思想最长连续不重复子序列数组元素的目标和题目讲解判断子序列双指针思想 双指针算法&#xff0c;就是可以将 n ^ 2 优化到 n。 最长连续不重复子序列 给定一个长度为 n 的整数序列&#xff0c;请找出最长的不包含重复的数的连续区间&#xff0c;输出它的长度…

IO流的学习

文章目录一、File类的使用创建File实例File常用方法总结二、IO流分类读入数据的基本操作步骤&#xff08;第一种&#xff09;步骤&#xff08;第二种&#xff09;写出数据的基本操作步骤读入并写出数据的基本操作&#xff08;复制&#xff09;步骤注意处理流之一&#xff1a;缓…

【Nginx】静态资源部署(下)

文章目录静态资源的缓存处理缓存概述浏览器缓存相关指令expires指令add_header指令Nginx的跨域问题解决同源策略跨域问题跨域问题的案例演示解决方案静态资源防盗链什么是资源盗链Nginx防盗链的实现原理&#xff1a;针对目录进行防盗链静态资源的缓存处理 缓存概述 什么是缓存…

【爪洼岛冒险记】第4站:Java中如何进行控制台输入输出?用Java实现猜数字小游戏;超详细讲解Java中的方法:方法的重载,方法的签名

&#x1f331;博主简介&#xff1a;是瑶瑶子啦&#xff0c;一名大一计科生&#xff0c;目前在努力学习JavaSE。热爱写博客~正在努力成为一个厉害的开发程序媛&#xff01; &#x1f4dc;所属专栏&#xff1a;爪洼岛冒险记【从小白到大佬之路】 ✈往期博文回顾:链接: 【爪洼岛冒…

【文件指针+文件顺序读写操作函数】

1.文件的打开和关闭 1.1 什么是文件指针 2.文件操作函数 2.1 fgetc函数和fputc函数2.2 fgets函数和fputs函数2.3 fscanf函数和fprintf函数2.4 fwrite函数和fread函数 1.文件的打开和关闭 1.1 什么是文件指针&#xff1f; 每个被使用的文件都在内存中开辟了一个相应的文件…

文件操作详解

文章目录前言一、什么是文件&#xff1f;1.程序文件2.数据文件3.文件名二、文件的打开和关闭1.文件指针2.文件的打开和关闭3.打开模式汇总4.例子三.操作函数介绍1.基本函数2.fseek2.ftell3.rewind4.feof尾话前言 恐怕很多人学完了c语言甚至不知道文件操作&#xff0c;也确实&am…

FPGA学习笔记-知识点3-Verilog语法1

1.关键字 2.运算符 按其功能可分为以下几类: 1) 算术运算符(,&#xff0d;,&#xff0c;/,&#xff05;) 2) 赋值运算符(,<) 3) 关系运算符(>,<,>,<) 4) 逻辑运算符(&&,||,!) 5) 条件运算符( ? &#xff1a;) 6) 位运算符(,|,^,&,^) …

【微信小程序】动态设置导航栏标题

&#x1f3c6;今日学习目标&#xff1a;第十八期——动态设置导航栏标题 &#x1f603;创作者&#xff1a;颜颜yan_ ✨个人主页&#xff1a;颜颜yan_的个人主页 ⏰预计时间&#xff1a;25分钟 &#x1f389;专栏系列&#xff1a;我的第一个微信小程序 文章目录前言使用配置文件…

消息中间件简介

UNIX的进程间通信就开始运用消息队列技术&#xff0c;一个进程将数据写入某个特定的队列中&#xff0c;其它进程可以读取队列中的数据&#xff0c;从而实现异步通信。对于如今的分布式系统&#xff0c;消息队列已经演变为独立的消息中间件产品&#xff0c;相比于RPC同步通信的方…

设计模式_行为型模式 -《模板方法模式》

设计模式_行为型模式 -《模板方法模式》 笔记整理自 黑马程序员Java设计模式详解&#xff0c; 23种Java设计模式&#xff08;图解框架源码分析实战&#xff09; 行为型模式用于描述程序在运行时复杂的流程控制&#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象都…

测试开发 | AppCrawler 自动遍历测试实践(三):动手实操与常见问题汇总

上两篇文章介绍了自动遍历的测试需求、工具选择和 AppCrawler 的环境安装、启动及配置文件字段基本含义&#xff0c;这里将以实际案例更加细致的说明配置文件的用法和一些特殊场景的处理。 实操演示 常规使用 下面我们继续之前的例子&#xff0c;在雪球搜索框输入搜索内容后的页…

代码随想录算法训练营第六天 | 哈希表理论基础,242.有效的字母异位词,349. 两个数组的交集, 202. 快乐数,1. 两数之和

第五天 周日 休息~【提醒补坑&#xff1a;链表总结还没写】一、参考资料哈希表理论基础文章连接&#xff1a;https://programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html有效的字母异位词题目链接/文章讲解/视频讲解&#xff1a;https:…

使用批处理__更改ip

1、使用.bat进行处理 echo off rem 测试更改ip netsh int ip set address "以太网 2" static 10.10.2.1 255.255.255.0 10.10.2.254 1 pause&exit 备注其他 echo #设静态IP netsh interface ip set address name"本地连接" sourcestatic addr192.16…

大坝安全监测解决方案 水库大坝安全监测系统改造工程方案

平升电子大坝安全监测系统根据SL551-2012《土石坝安全监测技术规范》的整编要求&#xff0c;设置了变形监测、渗流监测、环境量监测。借助大坝安全监测系统可及时了解大坝的工作性态和水库可能存在的事故隐患&#xff0c;为大坝安全管理与水库运行调度提供了准确、及时的现场信…

ElasticSearch7.10配置Search-Guard之配置用户

ElasticSearch7.10配置Search-Guard之配置用户 配置sg_internal_user.yml 密码是&#xff1a;elastic jode:hash: $2y$12$nUzkcjdnufzvI1HlmN7xSuND3skGhmwV5le5IINejz.asMFpLYNRybackend_roles:- "hr_department"psmith:hash: $2y$12$nUzkcjdnufzvI1HlmN7xSuND3sk…

[标准库]STM32F103R8T6 标准库配置RCC时钟和超频

前言 这篇博客总结一下学习到的配置时钟的方法。 从启动文件来看&#xff0c;MCU复位之后&#xff0c;执行到SystemInit()这个函数之后&#xff0c;会进入系统初始化设置&#xff0c;比如根据当前的MCU型号进入不同的条件编译语句&#xff0c;再配置相应的寄存器初始值&#…

mysql之一条mysql语句时如何执行的

请把连接器的功能说明一下? 连接器负责建立客户端和mysql服务器之间的连接.当客户端在中断输入连接命令(mysql -h -u -p),传输层使用tcp协议,通过三次握手建立连接. 如果mysql服务服务没有启动,会报错: 如果mysql服务正常启动,完成三次握手,在传输层建立连接后,会进行密码验证…

【云原生】k8s 一键部署(ansible)

文章目录一、概述二、Ansible 部署1&#xff09;开启记录日志2&#xff09;去掉第一次连接ssh ask确认3&#xff09;配置hosts三、开始编排 ansible playbook1&#xff09;创建目录2&#xff09;节点初始化3&#xff09;安装 docker4&#xff09;安装 k8s 相关组件5&#xff09…

2022 年 12 月区块链操作系统的开发回顾

正在寻找区块链操作系统组件的最新进展&#xff1f;你找对地方了&#xff01;正如在我们的路线图文章中所描述的那样&#xff0c;我们一直在朝着定期且频繁的更新方向发展着&#xff0c;以便让我们的社区能够及时的了解到我们取得的进展&#xff0c;以及将区块链操作系统提升到…