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

33c5ad031a694374825426e4107681f0.jpg

 

目录

 

1.进阶通讯录特点(下)

2.实现步骤

(1)保存增加的联系人数据到文件中

(2)加载保存的联系人数据

3.完整C语言通讯录代码

(1)contact.h

 (2)test.c

(3)contact.c

4.结语 


 

1.进阶通讯录特点(下)

①基本的增删查改功能;

②通讯录的空间不固定,大小可以调整;

③通过C语言文件操作来储存通讯录信息到硬盘上;

2.实现步骤

基本实现步骤同上、中两篇 【[C语言]通讯录实现(中) - CSDN App】http://t.csdnimg.cn/K5tqO

【【C语言】通讯录实现(上) - CSDN App】http://t.csdnimg.cn/ZrZQk

此外还有文件加载、写入、关闭等实现如下:

(1)保存增加的联系人数据到文件中

void SaveContact(Contact* pc)//保存联系人到文件中
{
	FILE* pf = fopen("contact.dat", "wb");//打开文件
	if (pf == NULL)//判断指针是否为空
	{
		perror("SaveContact");
		return;
	}
	//写数据
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data+i, sizeof(PeoInfo), 1, pf);//一回写一个大小为PeoInfo的文件
	//从pc->data+i的位置开始读写到文件中
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

运行后得到一个contact.dat的文件用记事本打开如图:

0296e054f4384527acc14b0c4ae65ae6.png

因为fopen函数的打开方式为“wb”,二进制写入模式所以打开该文件是一堆乱码 

3402a3e42fa34df3ba67e54a283b10c2.png

如上图所示生成了contact.dat文件

(2)加载保存的联系人数据

void LoadContact(Contact* pc)//加载已保存的联系人数据
{
	//打开文件
	FILE* pf = fopen("contact.dat", "rb");
	//以二进制形式读文件
	PeoInfo tmp = { 0 };//创建一个变量来存放读到的数据
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))//while循环一直读到文件末尾没有数据为止
	{
		if (CheckCapacity(pc) == 0)           //要先检查当前通讯录容量是否够存放保存的联系人
		{
			printf("无法加载联系人哦~\n");   //CheckCapacity为0时表示无法增容可能没办法开辟空间
			return;
		}
		pc->data[pc->sz] = tmp;          //将保存的联系人写入当前通讯录
		pc->sz++;                       //写入一个sz通讯录联系人数量加一和增加联系人函数一样
	}
	printf("已保存的联系人加载成功啦~\n");
	return;
}

3.完整C语言通讯录代码

(1)contact.h

#pragma once
//定义的的头文件contact.h
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30

#define DEFAULT_SZ 3
#define INT_SZ 2
enum OPTION//用枚举来定义变量
{
	EXIT,//0
	ADD,//1
	DEL,//2...
	SEARCH,
	MODIFY,
	SHOW,
	SORT
};


//声明类型
typedef struct PeoInfo //创建一个结构体来储存联系人相关信息
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
	int age;
}PeoInfo;

//通讯录
typedef struct Contact
{
	PeoInfo* data;//创建一个PeoInfo指针来指向存放数据的空间
	int sz;//用来记录联系人的个数
	int capacity;//记录通讯录当前最大容量
}Contact;

//函数声明
void InitContact(Contact* pc);
void AddContact(Contact* pc);
void ShowContact(const Contact* pc);
void DelContact(Contact* pc);
void SearchContact(const Contact* pc);
void DestroyContact(Contact* pc);
void SaveContact(Contact* pc);
void LoadContact(Contact* pc);//加载已保存的联系人数据





 (2)test.c

#define _CRT_SECURE_NO_WARNINGS 1
//test.c文件--流程
#include"contact.h"
void menu()//菜单
{
	printf("*******Contact******\n");
	printf("*** 1.ADD  2.DEL ***\n");
	printf("***** 3.SEARCH *****\n");
	printf("***** 4.MODIFY *****\n");
	printf("** 5.SHOE  6.SORT **\n");
	printf("****** 0.EXIT ******\n");

}
int main()//主函数
{
	int sec = 1;
	Contact con;
	InitContact(&con);//初始化通讯录
	LoadContact(&con);

	while (sec)
	{
		menu();
		scanf("%d", &sec);
		switch (sec)//选择不同的功能
		{
		case EXIT://退出
			SaveContact(&con);
			DestroyContact(&con);
			printf("您已退出\n");
			break;
		case ADD://加
			AddContact(&con);
			break;
		case DEL://删
			DelContact(&con);
			break;
		case SEARCH://查
			SearchContact(&con);
			break;
		case MODIFY://改
			break;
		case SHOW://显示
			ShowContact(&con);
			break;
		case SORT://分类
			break;
		default:
			printf("选择错误,请重新输入\n");
		}
		printf("\n");
	}
	return 0;
}

(3)contact.c

#define _CRT_SECURE_NO_WARNINGS 1
//contact函数实现contact.c源文件
#include"contact.h"

 int CheckCapacity(Contact* pc);
void LoadContact(Contact* pc)//加载已保存的联系人数据
{
	//打开文件
	FILE* pf = fopen("contact.dat", "rb");
	//读文件
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		if (CheckCapacity(pc) == 0)
		{
			printf("无法加载联系人哦~\n");
			return;
		}
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}
	printf("已保存的联系人加载成功啦~\n");
	return;
}
int Search_by_name(const Contact* pc)//查找函数
{

	char name[MAX_NAME] = { 0 };
	scanf("%s",name);
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}


void InitContact(Contact* pc) //初始化通讯录函数
{
	//memset(pc->data, 0, sizeof(pc->data));//静态版本
	assert(pc);
	pc->data = malloc(DEFAULT_SZ * sizeof(PeoInfo));//开辟空间
	if (pc->data == NULL)//判断指针是否为空
	{
		perror("InitContact");
		return;
	}
	pc->capacity = DEFAULT_SZ;//使用了宏定义DEFAULT_SZ=3容量
	pc->sz = 0;
}

int CheckCapacity(Contact* pc)//增容函数 加联系人时如果空间不够就增容
{
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INT_SZ)*sizeof(PeoInfo));
		//如果容量满了用realloc函数增容,INT_SZ宏定义为2
		if (ptr == NULL)
		{
			perror("CheckCapacity");
			return 0;
		}
		else
		{
			pc->data = ptr;//将增容后的指针赋给pc->data
			pc->capacity += INT_SZ;//capacity相应增加
			printf("增容成功\n");
		}
		return 1;
	}
	return 1;
}


void AddContact(Contact* pc)//增加联系人
{
	assert(pc);
	/*if (pc->sz == MAX)
	{
		printf("联系人已满\n");
		return;
	}*/
	if (0 == CheckCapacity(pc))
	{
		printf("无法增容哦~\n");
		return;
	}
	printf("请输入要添加的联系人名字、性别、年龄、电话、地址:\n");
	scanf("%s %s %d %s %s",pc->data[pc->sz].name, pc->data[pc->sz].sex,&pc->data[pc->sz].age, pc->data[pc->sz].tele,pc->data[pc->sz].addr);
	printf("您已经成功添加%s\n", pc->data[pc->sz].name);
	pc->sz++;
	return;
}

void ShowContact(const Contact* pc)//显示联系人
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("您还未添加联系人哦~快选择1去添加吧~\n");
		return;
	}
	int i = 0;
	printf("%-10s\t%-5s\t%-5s\t%-15s\t%-30s\t\n", "名字", "性别", "年龄", "电话", "住址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-5s\t%-5d\t%-15s\t%-30s\t\n",
			pc->data[i].name, pc->data[i].sex,
			pc->data[i].age, pc->data[i].tele,
			pc->data[i].addr);
	}
	return;
}

void DelContact(Contact* pc)//删除联系人
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("您还没有加联系人哦~快选择1去添加吧~\n");
		return;
	}
	printf("请输入要删除的联系人的名字:\n");
	int flag = Search_by_name(pc);
	if (flag == -1)
	{
		printf("没有找到该联系人哦~\n");
		return;
	}
	int j = 0;
	for (j = flag; j < pc->sz - 1; j++)
	{
		pc->data[j] = pc->data[j + 1];
	}
	printf("您已经成功删除该联系人\n");
	pc->sz--;
	return;
}

void SearchContact(const Contact* pc)//查找联系人并打印
{
	printf("请输入要查找的联系人的名字:\n");
	int i = Search_by_name(pc);
	if (i == -1)
	{
		printf("没有找到该联系人哦~\n");
		return;
	}
	else
	{
		printf("%-10s\t%-5s\t%-5d\t%-15s\t%-30s\t\n",
			pc->data[i].name, pc->data[i].sex,
			pc->data[i].age, pc->data[i].tele,
			pc->data[i].addr);
	}
	return;
}

//释放空间
void DestroyContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

void SaveContact(Contact* pc)//保存增加的联系人到文件中
{
	FILE* pf = fopen("contact.dat", "wb");//打开文件
	if (pf == NULL)//判断指针是否为空
	{
		perror("SaveContact");
		return;
	}
	//写数据
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data+i, sizeof(PeoInfo), 1, pf);//一回写一个大小为PeoInfo的文件
	//从pc->data+i的位置开始读写到文件中
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

4.结语 

三版通讯录循序渐进,从最开始的定容增删查改等功能的实现(上篇),到可以不定容的通讯录(中篇),最后到可以保存数据到文件并从文件中加载保存的联系人(下篇),我们不仅学会了一些基本函数的写法,还学了动态内存函数malloc,realloc等函数的用法,并熟悉了c语言文件的基本操作。

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Qt加密播放器】登录窗口功能补充

输入框小设计 目的&#xff1a;实现鼠标点击输入框时的聚焦效果。 首先在LoginForm构造函数中为账号和密码输入框添加事件过滤器。关于事件过滤器的具体介绍可以参考这篇博文&#xff1a;Qt消息机制和事件 ui->nameEdit->installEventFilter(this); ui->pwdEdit->…

文字超长显示省略号...坑(如果盒子本身是弹性盒子flex布局会不支持)

如果盒子是弹性盒子 样式会失效 #item-title{font-size: 28rpx;font-weight: 800;color: #2D3748;width: 100%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}&:nth-child(2){width: calc(100% - 172rpx);margin-left: 40rpx;>view{&:not(:first-…

人工智能基础-Numpy矩阵运算-聚合操作

加、减、乘、除、整除 幂、取余、倒数、绝对值 三角函数 e的x次方、3的x次方、logx、log2为底、log10为底 矩阵运算 加、减、乘&#xff08;对应数相乘&#xff09;、矩阵相乘运算、转至 向量和矩阵的运算 加法 对应相加 改变维度后相加 乘法 矩阵的逆 聚合操作 …

Java基础数据结构之Lambda表达式

一.语法 基本语法&#xff1a;(parameters)->expression或者(parameters)->{statements;} parameters&#xff1a;类似方法中的形参列表&#xff0c;这里的参数是函数式接口里面的参数。这里的参数可以明确说明&#xff0c;也可以不声明而由JVM隐含的推断。当只有一个推…

Android View解析

一、什么是View&#xff1f; 1.View是用户接口组件的基本构建块&#xff1b; 2.View在屏幕上占据一个矩形区域&#xff1b; 3.View通过绘制自己与事件处理两种方式与用户交互 设计View&#xff0c;主要是为了让应用能够与用户交互&#xff0c;要想完成交互&#xff0c;这个…

数据探索与可视化:可视化分析数据-下

目录 一、前言 二、介绍 Ⅰ.时间序列数据 Ⅱ.文本数据 Ⅲ.社交网络数据 三、结语 一、前言 那么本篇将互怼其他类型的数据分析的可视化方法进行介绍&#xff0c;它们分别是:时间序列&#xff0c;文本数据&#xff0c;社交网络数据。 二、介绍 Ⅰ.时间序列数据 import pan…

【python接口自动化】- 正则用例参数化

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

鸿蒙开发有必要学吗?看完这篇再决定吧

在科技的潮流中&#xff0c;每一次新操作系统的诞生都是对旧秩序的挑战与新机遇的孕育。鸿蒙操作系统的出现&#xff0c;无疑是近年来科技界最引人注目的事件之一。自华为于2019年正式推出鸿蒙系统以来&#xff0c;这一我们自主研发的操作系统不仅在国内引起巨大反响&#xff0…

在windows平台上mysql的安装教程

1.下载 mysql下载网址&#xff1a;https://dev.mysql.com/downloads/installer/ 这里直接选择的是mysql的社区版。自己使用直接选择免费的就行 直接选择下载 2.安装过程 选择Server only 就行 下一步 下一步 下一步&#xff0c;选择弱密码把&#xff0c;方便学习和自己使用 设置…

Java对象属性设置方式

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 对象属性设置方式 直接赋值 SystemMappingCode systemMappingCode new SystemMappingCode();systemMappingCode.setCodeResp(request.getCodeResp());systemMapping…

POI操作word表格,添加单元格,单元格对齐方法(不必合并单元格)

添加单元格&#xff0c;直接对row进行create新的cell&#xff0c;则会导致新创建的单元格与前面的单元格不对齐的现象。 //表格信息XWPFTable table doc.createTable();table.setWidth("100%");//第一行XWPFTableRow row0table.getRow(0);XWPFTableCell cell00row0.…

基于Python的招聘网站爬虫及可视化的设计与实现

摘要&#xff1a;现在&#xff0c;随着互联网网络的飞速发展&#xff0c;人们获取信息的最重要来源也由报纸、电视转变为了互联网。互联网的广泛应用使网络的数据量呈指数增长&#xff0c;让人们得到了更新、更完整的海量信息的同时&#xff0c;也使得人们在提取自己最想要的信…

Linux - iptables 防火墙

一. 安全技术和防火墙 1.安全技术 入侵检测系统&#xff08;Intrusion Detection Systems&#xff09;&#xff1a;特点是不阻断任何网络访问&#xff0c;量化、定位来自内外网络的威胁情况&#xff0c;主要以提供报警和事后监督为主&#xff0c;提供有针对性的指导措施和安全…

【C++游戏开发-01】推箱子

C游戏开发 文章目录 C游戏开发[TOC](文章目录) 前言一、逻辑分析1.1地图实现1.2人物的移动1.2.1小人移动1.2.2其他移动 1.3墙壁的碰撞1.4箱子的推动1.4.1什么时候推箱子1.4.2什么情况可以推箱子 1.5胜利的判断1.6卡关的处理1.7关卡的切换 二、DEMO代码2.1游戏框架2.2各功能函数…

【亲测有效】无法获得下列许可 SOLIDWORKS Standard 无效的(不一致的) 使用许可号码 (-8,544,0)

在观看本文章前&#xff0c;请注意看你的报错代码是否和我的一致&#xff0c;如果不是&#xff0c;直接跳过本文章。 前言&#xff1a;我安装的是SOLIDWORKS2022版&#xff0c;软件已经安装完毕&#xff0c;SolidWorks_Flexnet_Server文件夹里面的两个注册表已经安装完毕&#…

Python tkinter (7) ——Scale控件

Python的标准Tk GUI工具包的接口 tkinter系列文章 python tkinter窗口简单实现 Python tkinter (1) —— Label标签 Python tkinter (2) —— Button标签 Python tkinter (3) —— Entry标签 Python tkinter (4) —— Text控件 Python tkinter (5) 选项按钮与复选框 Pyt…

Stata收敛性分析(含详细代码说明和样例数据)

Stata收敛性分析&#xff08;含详细代码说明和样例数据&#xff09; 收敛性分析是管理科学和运筹学中重要的概念&#xff0c;是一种解决决策者对他们的管理策略的反馈的方式和手段。它的最终目的是帮助管理者从复杂的环境中筛选最优的解决方案。收敛性分析一般情况下会结合一些…

为客户解决痛点,电子纸增加制表功能

为客户解决痛点&#xff0c;电子纸增加制表功能 部分客户购买我们的电子纸后反馈效果很好&#xff0c;但是在配套组态软件制作电子纸模板时&#xff0c;遇到需要制作表格的时候比较麻烦。像是在画板作画一样&#xff0c;比较费时&#xff0c;而且效果不是很好&#xff0c;没办…

用VsCode写python

1.创建一个文件夹 2.创建.py文件 print("Hello World") print("*"*10) 4.运行 在终端版本fileName python3 app.py

MATLAB矩阵的操作(第二部分)

师从清风 矩阵的创建方法 在MATLAB中&#xff0c;矩阵的创建方法主要有三种&#xff0c;分别是&#xff1a;直接输入法、函数创建法和导入本地文件中的数据。 直接输入法 输入矩阵时要以中括号“[ ]”作为标识符号&#xff0c;矩阵的所有元素必须都在中括号内。 矩阵的同行元…