【C语言】从0到1带你学会文件版动态通讯录

news2024/9/23 1:41:45

🌇个人主页:平凡的小苏

📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情

🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html

小苏希望大家能从这篇文章中收获到许多,如果大家觉得这篇文章对你有帮助,请给小苏点赞+收藏+评论

 

目录

 通讯录思维导图

一、Contact.h 

二、Contact.c

1.初始化通讯录

 2.检查容量是否满

 3.添加联系人

4.显示联系人 

 5.查找联系人

6.修改联系人 

 7.通过名字来排序联系人

8.保存联系人到文本文件中 

9.从文件中读取联系人的信息 

10.销毁联系人

 三、text.c


 

 通讯录思维导图

一、Contact.h 

#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 11
#define ADDR_MAX 30
#define INIT_CAPA 3
#define INC_CAPA 2
typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;
//动态版本
typedef struct Contact
{
	PeoInfo* data;
	int sz;//表示通讯录有多少个联系人
	int capacity;//表示通讯录的最大容量
}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//添加联系人
void AddContact(Contact* pc);
//删除联系人
void DelContact(Contact* pc);
//显示通讯录
void ShowContact(const Contact* pc);
//查找联系人
void SearchContact(Contact*pc);
//修改联系人’
void ModifyContact(Contact*pc);
//通过名字排序联系人
void ByNameSortContact(Contact* pc);
//销毁联系人
void DestroyContact(Contact* pc);
//保存联系人到文本文件中
void SaveContact(Contact* pc);
//从文件中读取联系人的信息
void GetContact(Contact* pc);

这些是头文件的包含,函数的声明,以及#define定义的常量,为了以后修改方便

二、Contact.c

1.初始化通讯录

void InitContact(Contact* pc)//初始化通讯录
{
	assert(pc!=NULL);
	pc-> sz = 0;
	pc->capacity = INIT_CAPA;
	PeoInfo * ptr = (PeoInfo*)calloc(INIT_CAPA, sizeof(PeoInfo));
	if (ptr == NULL)
	{
		perror("InitContact");
		return;
	}
	pc->data = ptr;
	GetContact(pc);
}

 初始化通讯录的容量开始为3,sz初始时为0,动态开辟的ptr开辟成功在赋给data。

 2.检查容量是否满

void check_capacity(Contact* pc)//检查容量是否满
{
	assert(pc);
	if (pc->capacity == pc->sz)
	{
		PeoInfo*ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			perror("check_capacity");
			return;
		}
		pc->data = ptr;
		pc->capacity += INC_CAPA;
		printf("增容成功\n");
	}
}

如果容量满,则每次增容两个,如果想要增容更多,则修改define定义的常量就可以修改了。

realloc开辟的时候有可能是用pc->data来往后扩大增容,也有可能是用新的空间来开辟,为了防止开辟失败,使原有的数据丢失,则先使用新的指针变量来接收动态开辟的空间,如果开辟成功,再将它赋给data。

 3.添加联系人

void AddContact(Contact* pc)//添加联系人
{
	assert(pc != NULL);
	check_capacity(pc);
	printf("请输入姓名:\n");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:\n");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:\n");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入号码:\n");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:\n");
	scanf("%s", pc->data[pc->sz].addr);
	printf("添加联系人成功\n");
	pc->sz++;
}

添加联系人前,需要先判断是否需要增容

4.显示联系人 

void ShowContact(const Contact* pc)//显示联系人
{
	assert(pc != NULL);
	printf("%-20s\t%-4s\t%-4s\t%-12s\t%-30s\n","姓名","年龄","性别","电话号码","地址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-4d\t%-4s\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);
	}
}

 5.查找联系人

int ByNameFind(Contact* pc, char name[])//通过名字查找联系人
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}
void SearchContact(Contact* pc)//查找联系人
{
	assert(pc);
	char name[NAME_MAX];
	printf("请输入要查找的联系人\n");
	scanf("%s", name);
	int ret = ByNameFind(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	
	printf("%-20s\t%-4s\t%-4s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话号码", "地址");
	printf("%-20s\t%-4d\t%-4s\t%-12s\t%-30s\n", pc->data[ret].name,
		pc->data[ret].age,
		pc->data[ret].sex,
		pc->data[ret].tele,
		pc->data[ret].addr);
}

注意:名字属于字符串,名字的比较需要用strcmp来比较,如果返回-1,则是没有找到联系人,如果找到了,则就打印这个联系人的信息出来

6.修改联系人 

void ModifyContact(Contact* pc)//修改联系人
{
	assert(pc);
	char name[NAME_MAX];
	printf("请输入要修改的联系人姓名\n");
	scanf("%s", name);
	int pos = ByNameFind(pc, name);
	if (pos == -1)
	{
		printf("找不到该联系人\n");
		return;
	}
	printf("请输入姓名:\n");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:\n");
	scanf("%d", &(pc->data[pos].age));
	printf("请输入性别:\n");
	scanf("%s", pc->data[pos].sex);
	printf("请输入号码:\n");
	scanf("%s", pc->data[pos].tele);
	printf("请输入地址:\n");
	scanf("%s", pc->data[pos].addr);
	printf("修改联系人成功\n");
}

注意:想要修改这个联系人,也需要通讯录中有这个联系人,所以要先查找到这个联系人,所以调用封装好的通过名字查找联系人这个函数就可以了,如果返回-1,则就是没有该联系人,无法修改,如果找到了,则才能够修改此联系人的信息。

 7.通过名字来排序联系人

void ByNameSortContact(Contact* pc)//通过名字来排序
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("无联系人,无法排序\n");
		return;
	}
	PeoInfo temp;
	for (int i = 0; i < pc->sz - 1; i++)
	{
		for(int j = 0 ;j<pc->sz-1-i;j++)
		{
			if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
			{
				temp = pc->data[j];
				pc->data[j] = pc->data[j + 1];
				pc->data[j + 1] = temp;
			}
		}
		
	}
	printf("排序成功\n");
}

注意:这里通过名字来排序联系人,也是需要用到strcmp这个库函数的,strcmp是一个字符来比较的,如果有一个字符大的话就要进行交换,利用的是冒泡排序思想来排序联系人的

8.保存联系人到文本文件中 

void SaveContact(Contact* pc)
{
	assert(pc);
	
	FILE* pf = fopen("Contact.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
	}
	else
	{
		for (int i = 0; i < pc->sz; i++)
		{
			fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
		}
		fclose(pf);
		pf = NULL;
		printf("保存数据成功\n");
	}
}

注意:FILE是C语言标准的指针,wb是用二进制的方式写入文本文件中,而fwrite的用法我们可以利用cplusplus来查找它的用法,里面介绍了它的每个参数的用法,第一个参数ptr其实就是传我们的data的指针进去,第二个参数本质就是求大小的,求得是PeoInfo得大小,第三个参数就是每次添加几个联系人,每次添加1个。第四个参数是把文件流放入

9.从文件中读取联系人的信息 

//从文件中初始化联系人
void GetContact(Contact* pc)
{
	assert(pc);

	FILE* pf = fopen("Contact.txt", "rb");
	if (pf == NULL)
	{
		perror("GetContact::fopen");
	}
	else
	{
		PeoInfo ptr = { 0 };
		int i = 0;
		while (fread(&ptr, sizeof(PeoInfo), 1, pf))
		{
			check_capacity(pc);
			pc->data[i] = ptr;
			i++;
			pc->sz++;
		}
		fclose(pf);
		pf = NULL;
	}
}

注意:rb是利用二进制来读取联系人的,fread的用法如上图所示。

10.销毁联系人

//销毁联系人
void DestroyContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

注意:在我们退出通讯录时,要将它进行销毁 

 三、text.c

#include"Contact.h"
void menu()
{
	printf("**********************************\n");
	printf("*******1.Add      2.Del   ********\n");
	printf("*******3.Search   4.Modify********\n");
	printf("*******5.Show     6.Sort  ********\n");
	printf("*******0.exit             ********\n");
	printf("**********************************\n");
}
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT

};
int main()
{
	Contact con;
	InitContact(&con);
	int input = 0;
	do
	{
		menu();
		printf("请输入数字:\n");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL :
			DelContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT:
			ByNameSortContact(&con);
			break;
		case EXIT:
			SaveContact(&con);
			DestroyContact(&con);
			printf("退出程序\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;

注意:首先要建立菜单,然后用枚举来定义case后面,这样为了可以让我们看代码更清晰,在运行程序时要将联系人从文件中读取出来,在退出文件时,要把联系人保存到文本文件中去,在进行销毁。

 好了,小编的分享到这里就结束了,如果有什么不足的地方请大佬多多指教!!!

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

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

相关文章

初学者试试,HarmonyOS应用开发者基础认证

一些初学HarmonyOS应用开发的同学往往不知道如何开始&#xff0c;建议先试试《HarmonyOS应用开发者基础认证》&#xff0c;基础认证是华为进一步大范围布局推广“鸿蒙世界”的新举措。也是初学者开启鸿蒙世界的一把钥匙。 【说说鸿蒙世界】 相信大家已经对鸿蒙不陌生了&#x…

IDEA新建js项目和执行js脚本

一)、安装Node.js具体操作参考:https://blog.csdn.net/xijinno1/article/details/128774375二)、IDEA中新建js项目(hello world)1.按照下图&#xff0c;新建js项目2.选中示例代码文件后点击运行->运行3.选择【编辑配置】4.更新一下节点解释器(nodejs.exe)&#xff0c;点击运…

界面组件DevExpress WPF v22.2 - Windows 11暗黑主题发布

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

Unity 之 Addressable可寻址系统 -- 资源远程加载 | 资源预下载

可寻址系统远程加载 -- 资源预下载 -- 进阶&#xff08;三&#xff09;一&#xff0c;Unity 云资源分发 -- 使用介绍1.1 CCD 的介绍1.2 后台准备工作二&#xff0c;CDD的使用2.1 CCD可视化界面的使用2.2 CDD命令行界面使用2.2.1 准备工作2.2.2 CLI 用法三&#xff0c;AA CCD资…

Qt扫盲-QObject对象和线程

QObject对象和线程一、概述二、QObjectReentrant性三、每个线程事件的循环四、从其他线程访问QObject的子类五、跨线程的信号和槽函数一、概述 QThread继承QObject。QThread它发出信号来指示线程开始或结束执行&#xff0c;还提供了一些任务槽。 Qobject可以在多个线程中使用…

L1-006 连续因子

一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3567&#xff0c;其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N&#xff0c;要求编写程序求出最长连续因子的个数&#xff0c;并输出最小的连续因子序列。 输入格式&#xff1a; 输入在一行中给出一…

Python爬虫(1)一次性搞定Selenium(新版)8种find_element元素定位方式

selenium中有8种不错的元素定位方式&#xff0c;每个方式和应用场景都不一样&#xff0c;需要根据自己的使用情况来进行修改 这里写目录标题1.id定位2.CSS定位3.XPATH定位4.name定位5.class_name定位6.Link_Text定位7.PARTIAL_LINK_TEXT定位8.TAG_NAME定位总结目前selenium已经…

力扣SQL刷题

目录标题571. 给定数字的频率查询中位数574. 当选者608. 树节点612. 平面上的最近距离619. 只出现一次的最大数字571. 给定数字的频率查询中位数 题型&#xff1a;给出数值和对应频率&#xff0c;返回中位数 解答&#xff1a;分别升序和降序排列。中位数正序和倒序所处的位置都…

人工智能图片素材高清,机器人图片卡通 素材

1、做一个人工智能的ppt需要哪些素材 不能理解你的问题。ppt仅仅是一个做幻灯的软件&#xff0c;可以插入图片、动画、音乐、过场等幻灯的功能&#xff0c;还谈不上有人工智能的能力。人工智能需要有更为强大的类似人脑思维的能力&#xff0c;简单的说人工智能是可以思考的机器…

【HBase——陌陌海量存储案例】2. HBase表结构设计(中)

前言 本文是陌陌海量存储案例——HBase表结构设计&#xff08;中&#xff09;&#xff0c;介绍ROWKEY设计原则、项目初始化。 4.5 ROWKEY设计原则 4.5.1 HBase官方的设计原则 避免使用递增行键/时序数据 如果ROWKEY设计的都是按照顺序递增&#xff08;例如&#xff1a;时间…

信息论复习—差错控制编码

目录 差错控制编码的基本概念&#xff1a; 差错控制编码的主要类型和方式&#xff1a; 差错控制编码的主要类型&#xff1a; 差错控制方式&#xff1a; 简单的差错控制方法&#xff1a; 奇偶校验码&#xff1a; 重复码&#xff1a; 信道编码的基本概念和定理*: 信道编…

4 反向传播

文章目录问题提出计算图中的神经网络改进&#xff08;激活函数&#xff09;反向传播前馈计算反向传播pytorch当中的前馈与反馈Tensor张量课程代码课后作业课程来源&#xff1a; 链接课程内容部分来源&#xff08;觉得归纳的非常好的&#xff09;&#xff1a; 链接以及&#xff…

MySQL中的运算符

目录 一.运算符 简介 算术运算符 比较运算法 逻辑运算符 位运算符 实例演示 一.运算符 简介 数据库中的表结构确立后&#xff0c;表中的数据代表的意义就已经确定。通过MySQL运算符进行运算&#xff0c;就可以获取到表结构以外的另一种数据。 例如&#xff0c;学生表中…

[数据结构笔记]二叉树初阶

基本知识 树 -节点的度&#xff1a;一个节点含有的子树的个数称为该节点的度&#xff1b; -叶节点或终端节点&#xff1a;度为0的节点称为叶节点&#xff1b; -非终端节点或分支节点&#xff1a;度不为0的节点&#xff1b; -父节点&#xff1a;若一个节点含有子节点&#xff…

Mybatis 通过接口实现 sql 执行原理解析

使用过 mybatis 框架的小伙伴们都知道&#xff0c;mybatis 是个半 orm 框架&#xff0c;通过写 mapper 接口就能自动实现数据库的增删改查&#xff0c;但是对其中的原理一知半解&#xff0c;接下来就让我们深入框架的底层一探究竟1、环境搭建首先引入 mybatis 的依赖&#xff0…

Consul服务注册与发现

目录 一、Consul简介 &#xff08;一&#xff09;官网 &#xff08;二&#xff09;特点 二、安装并运行Consul &#xff08;一&#xff09;官网安装说明 &#xff08;二&#xff09;下载 &#xff08;三&#xff09;使用开发模式启动 三、服务提供者 四、服务消费者 …

怎么压缩pdf文件?选对方法其实很简单!

相信许多人在使用设备的时候都会面对这样一个问题&#xff0c;那就是设备内存不足。仿佛不管我们多么努力的节省空间&#xff0c;总是会到头来遇到储存空间不足得难题&#xff0c;尤其是一些比较大的pdf文件&#xff0c;特别占据我们的设备内存&#xff0c;那么你知道怎么压缩p…

0128 Web API基本认知

作用使用JS去操作html和浏览器分类DOM&#xff08;文档对象模型&#xff09;BOM&#xff08;浏览器对象模型&#xff09;DOM是什么&#xff1a;Document Object Model-----文档对象模型&#xff0c;用来呈现以及与任意HTML或XML文档交互的API&#xff0c;浏览器提供的一套专门用…

【Linux】一文掌握Linux权限

环境&#xff1a;centos7&#xff0c;腾讯云服务器Linux文章都放在了专栏&#xff1a;【Linux】欢迎支持订阅&#x1f339;前言权限 一词相信大家都不陌生&#xff0c;与我们的生活密切相关。小区里的门禁制度、公司里的管理制度、学校里的校规规定、甚至是社交平台上的一些设置…

python 手机相机传感器信息计算

传感器信息计算 输入传感器尺寸以上已红米12pro为例 输入传感器尺寸 1/1.4英寸 0.7142857 输入像素2亿 200000000 得到以下结果 和宣传中的传感器信息一致 附源码 import sympyclass CMosInfo(object):"""传感器信息计算"""def __init__(…