前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C语言】通讯录《信息写到文件版本》

【C语言】通讯录《信息写到文件版本》

作者头像
謓泽
发布2022-12-19 14:47:03
1.2K0
发布2022-12-19 14:47:03
举报
文章被收录于专栏:【C】系列【C】系列

🚩write in front🚩    🔎大家好,我是謓泽,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 🏅2021年度博客之星物联网与嵌入式开发TOP5~2021博客之星Top100~阿里云专家博主 & 星级博主~掘金⇿InfoQ~51CTO创作者新人榜No.7~周榜257﹣总榜931⇿全网访问量40w+🏅 🆔本文由 謓泽 原创 CSDN首发🙉如需转载还请通知⚠ 📺创作时间 ↔ 2021年3月18日◬ 📝个人主页-謓泽的博客_CSDN博客 📃 🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​ 📣系列专栏-YY_謓泽的博客-CSDN博客🎓 ✉️我们并非登上我们所选择的舞台,演出并非我们所选择的剧本📩

目录

🚩write in front🚩   

概述 

增添の功能

Save_Contact() → 保存通讯录信息

读文件操作 

模块化代码实现 

Ⅰ→  test.c

Ⅱ→address_book.h

Ⅲ→address_book.c

✨最后✨

概述 

这个是在之前的动态版本进行添加,如果你不清楚通讯录的静态或者是动态怎么实现。可以看看博主写的前面两篇通讯录的静态和动态的实现↓ 🍖链接→🍖【C语言】通讯录《静态内存版本》_謓泽的博客-CSDN博客 🍗链接→🍗【C语言】通讯录《动态内存版本》_謓泽的博客-CSDN博客


增添の功

相比之前的静态版本还是动态版本。这个信息写到文件版本,无疑是更加完善的。如果你不会文件操作的话,可以看看我前面写过的内存的一篇博客来看看⇣

链接→【C语言】内存函数_謓泽的博客-CSDN博客

增添の功能↓

(1)→当通讯录退出的时候,把信息写到文件里面。

(2)→当通讯录初始化的时候,加载文件的信息到通讯录当中去。

在上述的博客当中我们是↓

代码语言:javascript
复制
Destory_Contact(&con);//销毁通讯录

而在这篇博客我们实现的是首先要保存通讯录,也就是保存信息到文件去。那么我们创建一个函数实现保存信息到文件里。

代码语言:javascript
复制
Save_Contact(&con);//保存信息到文件

Save_Contact() → 保存通讯录信息

那么首先我们要实现这个保存通讯录信息到文件的这个函数。 Save_Contact() 代码示例如下↓

代码语言:javascript
复制
//读写信息到文件
void Save_Contact(Contact* pc)
{
	FILE* pf = fopen("information.txt","w");
	//返回值判断
	if (pf == NULL)
	{
		perror("Save_Contact:");
		return;
	}
	//写文件
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		//数组名+i就是数组名下标元素的地址。
		fwrite(pc->date + i, sizeof(information), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

那么现在我们就可以试一下,那我们就把张三同学的通讯录信息写下。 张三:?????????????,算了为了张三同学的隐私我们就不这样了(o゚v゚)ノ 直接简单一点打印输入数字①来康康吧。

从上述的截屏当中可以知道我们是写入进去东西的。


读文件操作 

现在我们保存文件是没有任何的问题了,但是当我们再次运行通讯录的时候。通讯录依然会什么都会没有。所以,此时我们就需要进行读文件的一个操作。

我们在初始化的时候就可以进行读文件的一个操作了,因为在此之前已经有增删查改了。

那我们封装一个函数用read_file()来进行实现。 

代码语言:javascript
复制
void read_file(Contact* pc)
{
	FILE* pf = fopen("information.txt", "r");
	//返回值判断
	if (pf == NULL)
	{
		perror("read_file");
		return;
	}
	//读文件
	information tmp = {0};//问题:读文件停止(不知道你写入几个信息)?返回值的问题实际count
	while (fread(&tmp, sizeof(information), 1, pf))//读不到返回0
	{
		//是否增容
		Cap_inc(pc);
		//存放增容元素
		pc->date[pc->sz] = tmp;
		//加载信息
		pc->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

让我们来看看是否能进行一个读文件的操作。检测是非常简单的,我们先输入一个张三,再退出程序。然后,再输入一个李四。看看能不能读写上次张三的信息。 输入界面数字:6 即可(o゚v゚)ノ 第一次的输入! 

上述的读写操作是成功的。 

第二次的输入!

从这里我们可以知道它保存了我们上述的读写的值,也就是读文件的操作我们是成功的了。


模块化代码实现 

Ⅰ→  test.c

代码示例如下↓

代码语言:javascript
复制
/*
	@Note1:当通讯录退出的时候,把信息写道文件。
	@Note2:当通讯录初始化的时候,加载文件的信息。
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include"a.h"
#include<Windows.h>
#pragma warning(disable:6031)
//颜色函数
void color(short x)
{
	if (x >= 0 && x <= 15)
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);
	else
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
//创建菜单函数
void menu()
{
	color(0);//黑色
	system("cls");//清屏

	color(12);//白色
	printf("¤--------------------------------------------¤\n");
	printf("|■■■■■■■■→通讯录v1.0←■■■■■■■■|\n");
	printf("|———————————————————————|\n");
	printf("|★★★★★→1.increase ■ 2.deLete←★★★★★|\n");
	printf("|★★★★★→3.find     ■ 4.Revise←★★★★★|\n");
	printf("|★★★★★→5.Check    ■ 6.Print ←★★★★★|\n");
	printf("|★★★★★→0.Exit     ■         ←★★★★★|\n");
	printf("|———————————————————————|\n");
	printf("|■■■■■■■■→通讯录v1.0←■■■■■■■■|\n");
	printf("¤--------------------------------------------¤\n");
}
enum Number
{
	Exit,
	Increase,
	DeLete,
	Find,
	Revise,
	Check,
	Print,
};
int main(void)
{
	menu();
	int input = 0;
	//当然初始化全0:Contact con = {0};也是可以的,当然我们这里的初始化不是这样的原因是可以应对比较复杂的问题。
	Contact con;//初始化通讯录
	//给date申请一块连续的内存空间存放在堆区上。
	InitContact(&con);
	do
	{
		color(5);
		printf("¤----------------¤\n");
		printf("|请输入界面上的数字|:");
		scanf("%d", &input);
		printf("¤----------------¤\n");
		color(1);
		switch (input)
		{
		case Exit:
			//销毁之前先保存。
			Save_Contact(&con);
			//把通讯录里面的内存空间date给释放掉。
			Destory_Contact(&con);//销毁通讯录。
			printf("══════════════@\n");
			printf("退出通讯录v1.0@\n");
			printf("══════════════@\n");
			break;
		case Increase:
			//增加人的信息,放在通讯录当中去。
			Add_Contact(&con);
			break;
		case DeLete:
			//删除通讯人的信息
			DeLete_Contact(&con);
			break;
		case Find:
			//查找指定通讯录人的信息
			Find_Contact(&con);
			break;
		case Revise:
			//修改指定通讯录人的信息
			Revise_Contact(&con);
			break;
		case Check:
			//排查通讯录当中人员的信息
			Check_Contact(&con);
			break;
		case Print:
			//打印通讯录当中人员的信息。
			Print_Contact(&con);
			break;
		default:printf("你输入的数字找不到,请重新输入~\n");
		}
	} while (input);
	return 0;
}

Ⅱ→address_book.h

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h> 
#include<stdlib.h>
#include<Windows.h>
#include<string.h>

#define Max_name 5
#define Max_age 100
#define Max_genger 3
#define Max_address 20
#define Max_telephone 20

//#define num 1000 //静态的存放
#define Defsz 3 //一开始的值
#define Inc 2  //每次的增量

//类型的定义
typedef struct information
{
	//名字、年龄、性别、电话、地址。
	char name[Max_name];
	char age[Max_age];
	char genger[Max_genger];
	char telephone[Max_telephone];
	char address[Max_address];
}information;

//通讯录 - 动态版本
typedef struct Contact
{
	//这里用了个结构体嵌套
	information* date;//指向动态内存的申请空间,用于存放联系人的信息。
	int sz;//记录当前通讯录有效信息的个数。
	int capacity;//表示当前通讯录的最大"容量"大小。
}Contact;

//初始化通讯录
void InitContact(Contact* pc);
//增加通讯录信息
void Add_Contact(Contact* pc);
//打印通讯录的信息
void Print_Contact(const Contact* pc);
//删除通讯人的信息
void DeLete_Contact(Contact* pc);
//查找指定通讯录人的信息
void Find_Contact(Contact* pc);
//修改指定通讯录人的信息
void Revise_Contact(Contact* pc);
//排查通讯录当中人员的信息
void Check_Contact(Contact* pc);
//销毁通讯录
void Destory_Contact(Contact* pc);

//保存通讯录信息到文件
void Save_Contact(Contact* pc);

//读文件-加载文件
void read_file(Contact* pc);

//检测增容
void Cap_inc(Contact* pc);

Ⅲ→address_book.c

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1
#include"address_book.h"

//读文件-加载文件
void read_file(Contact* pc)
{
	FILE* pf = fopen("information.txt", "r");
	//返回值判断
	if (pf == NULL)
	{
		perror("read_file");
		return;
	}
	//读文件
	information tmp = {0};//问题:读文件停止(不知道你写入几个信息)?返回值的问题实际count
	while (fread(&tmp, sizeof(information), 1, pf))//读不到返回0
	{
		//是否增容
		Cap_inc(pc);
		//存放增容元素
		pc->date[pc->sz] = tmp;
		//加载信息
		pc->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

//动态版本进行初始化
void InitContact(Contact* pc)
{
	pc->date = (information*)malloc(Defsz * sizeof(information));
	if (pc->date == NULL)
	{
		perror("InitContact");
		return;
	}
	//如果返回的为空指针的情况
	pc->sz = 0;//sz初始化
	pc->capacity = Defsz;//当前最大"容量"

	//读文件-加载文件
	read_file(pc);
}

//增容函数
void Cap_inc(Contact* pc)
{
	//当记录当前通讯录有效信息的个数 等于 表示当前通讯录的最大"容量"大小。
	if (pc->sz == pc->capacity)
	{
		//给堆区增加"容量",因为空间不够。
		information* pa = (information*)realloc(pc->date, (pc->capacity + Inc)*(sizeof(information)));
		if (pa != NULL)
		{
			pc->date = pa;//把这块空间移交到date进行维护
			pc->capacity = pc->capacity + Inc;//由于这里我们进行了增容也需要把容量改变成+Inc的值

			printf("增加联系人已成功(@^0^)\n");
		}
		//增容失败
		else
		{
			perror("Add_Contact:");
			printf("增加联系人失败!(ToT)/~~~\n");
			return;
		}
	}
}

//动态版本增加
void Add_Contact(Contact* pc)
{
	//检测容量
	Cap_inc(pc);
	//增加一个人的信息
	printf("\n");
	printf("请输入增加人的名字->:");
	scanf("%s", pc->date[pc->sz].name);//注意→数组名是首元素地址,所以不用进行取地址.

	printf("请输入增加人的年龄->:");
	scanf("%s", pc->date[pc->sz].age);

	printf("请输入增加人的性别->:");
	scanf("%s", pc->date[pc->sz].genger);

	printf("请输入增加人的电话->:");
	scanf("%s", pc->date[pc->sz].telephone);

	printf("请输入增加人的地址->:");
	scanf("%s", pc->date[pc->sz].address);
	//成功~
	pc->sz++;
	printf("★恭喜你~添加信息成功★\n");
	printf("\n");
}

//读写信息到文件
void Save_Contact(Contact* pc)
{
	FILE* pf = fopen("information.txt","w");
	//返回值判断
	if (pf == NULL)
	{
		perror("Save_Contact:");
		return;
	}
	//写文件
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		//数组名+i就是数组名下标元素的地址。
		fwrite(pc->date + i, sizeof(information), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

void Print_Contact(const Contact* pc)
{
	int i = 0;
	//打印标题栏的信息
	printf("|-------------------------------------------------------|\n");
	printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", "名字", "年龄", "性别", "电话", "地址");

	for (i = 0; i < pc->sz; i++)
	{
		printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", pc->date[i].name,
			pc->date[i].age,
			pc->date[i].genger,
			pc->date[i].telephone,
			pc->date[i].address);
	}
}

static int FindByname(Contact* pc, char name[])
{
	int i = 0;
	//用for循环进行遍历
	for (i = 0; i < pc->sz; i++)
	{
		//strcmp()比较字符串
		if (strcmp(pc->date[i].name, name) == 0)
		{
			return i;//返回下标
		}
	}
	return -1;
}

void DeLete_Contact(Contact* pc)
{
	char name[Max_name] = { 0 };
	//通讯录为空的时候
	if (pc->sz == 0)
	{
		printf("通讯录当中没有任何信息\n");
		return;
	}
	printf("请输入你要删除的名字->:");
	scanf("%s", name);
	//查找要删除的人:有/没有
	int ret = FindByname(pc, name);
	if (ret == -1)
	{
		printf("没有查找到当前人的信息\n");
		return;
	}
	//删除
	int i = 0;
	for (i = ret; i < pc->sz - 1; i++)
	{
		pc->date[i] = pc->date[i + 1];
	}
	pc->sz--;//因为我们删除成功下标要减1
	printf("★恭喜你~删除信息成功★\n");
	printf("\n");
}

void Find_Contact(Contact* pc)
{
	char name[Max_name] = { 0 };
	printf("请输入你要查找的名字->:");
	scanf("%s", name);
	int ret = FindByname(pc, name);
	if (ret == -1)
	{
		printf("没有查找到当前人的名字\n");
		return;
	}
	else
	{
		printf("|-------------------------------------------------------|\n");
		printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", "名字", "年龄", "性别", "电话", "地址");

		printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", 
			pc->date[ret].name,
			pc->date[ret].age,
			pc->date[ret].genger,
			pc->date[ret].telephone,
			pc->date[ret].address);
		printf("查找%sの信息成功~\n", pc->date[ret].name);
	}
}

void Revise_Contact(Contact* pc)
{
	char name[Max_name] = { 0 };
	printf("请输入你要修改通讯录人的名字->:");
	scanf("%s", name);
	int ret = FindByname(pc, name);
	if (ret == -1)
	{
		printf("当前修改人的信息不存在\n");
		return;
	}
	else
	{
		printf("请输入修改人的名字->:");
		scanf("%s", pc->date[ret].name);//注意→数组名是首元素地址,所以不用进行取地址.

		printf("请输入修改人的年龄->:");
		scanf("%s", pc->date[ret].age);

		printf("请输入修改人的性别->:");
		scanf("%s", pc->date[ret].genger);

		printf("请输入修改人的电话->:");
		scanf("%s", pc->date[ret].telephone);

		printf("请输入修改人的地址->:");
		scanf("%s", pc->date[ret].address);
		printf("恭喜你,修改成功~\n");
	}
}

int sort_name_max(const void* e1, const void* e2)
{
	return (strcmp(((struct Contact*)e1)->date->name, ((struct Contact*)e2)->date->name));
}

void Check_Contact(Contact* pc)
{
	//qosrt()函数首字母进行排序
	qsort(pc->date, pc->sz, sizeof(pc->date[0]), sort_name_max);
	printf("|-------------------------------------------------------|\n");
	printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", "名字", "年龄", "性别", "电话", "地址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", pc->date[i].name,
			pc->date[i].age,
			pc->date[i].genger,
			pc->date[i].telephone,
			pc->date[i].address);
	}
}

void Destory_Contact(Contact* pc)
{
	//销毁通讯录实际上就是把date给释放掉,free()函数进行回收即可。
	free(pc -> date);
	pc->date = NULL;
	pc->sz = 0;
	pc->capacity = 0;
	//记得清0☆⌒(*^-゜)v THX!!
}

✨最后✨

那么这个就已经实现了通讯录的最终版本了,这个项目适合已经把C语言学完的人做。巩固自己以往的能力,做个这个提升自己逻辑思维和代码能力的一个小的项目

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述 
  • 增添の功
  • Save_Contact() → 保存通讯录信息
  • 读文件操作 
  • 模块化代码实现 
    • Ⅰ→  test.c
      • Ⅱ→address_book.h
        • Ⅲ→address_book.c
        • ✨最后✨
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档