练手项目层高阶3—《详解文件版本——通讯录管理系统》

本文介绍了如何使用C语言中的文件操作功能,将通讯录数据(PeoInfo结构体)保存到文件(contact_data.txt)中,以及从文件中读取数据并显示在控制台。通过`ConSL`结构实现了写入、读取、初始化和销毁等功能。
摘要由CSDN通过智能技术生成

在这里插入图片描述

🚩前言

我们前面写的两种方法(静态和动态),唯一缺点就是每次运行都要输入新的数据,很麻烦,也就是说写入的数据无法长久保存,代码运行结束后就立即释放了。所以,接下来就用文件操作的知识点,把写入的数据导入到文件中去。

🧩框架结构

由于我在前面的两篇文章中说了具体的项目需求,因此在这片当中我直接说编写代码的不同点。

文件编写通讯录,主要是多了文件读操作、写操作2个部分,下面就是这2个代码块,注意的就是文件记得即使关闭。

写操作,把数据录入到文件中去。

//文件写操作函数
void save_contact(ConSL* con)
{
	assert(con);
	FILE* pf_wirte = fopen("contact_data.txt", "wb");
	if (pf_wirte == NULL)
	{
		perror("save_contact fopen error!\n");
		return;
	}
	//写入 文件中
	for (int i = 0; i < con->size; i++)
	{
		fwrite(con->data+i, sizeof(PeoInfo), 1, pf_wirte);
		//把每个结构体类型中的信息写入到文件中去
	}
	printf("数据保存成功!\n");

	//关闭
	fclose(pf_wirte);
	pf_wirte = NULL;
}

读操作,把文件中的信息显示到控制台上。

//文件读操作函数
void load_contact(ConSL* con)
{
	PeoInfo temp = { 0 };//临时变量
	assert(con);
	FILE* pf_read = fopen("contact_data.txt", "rb");
	if (pf_read == NULL)
	{
		perror("load_contact fopen error!\n");
		return;
	}
	//循环读取文件中的内容
	while (fread(&temp,sizeof(PeoInfo),1,pf_read))//返回0的时候就读取完了
	{
		//读的时候,需要判断文件中的数据个数,在申请的空间中是否能存储完
		check_capacity(con);
		//用临时变量存储,再赋值给申请的空间中去
		con->data[con->size++] = temp;
	}
	//记得关闭文件
	fclose(pf_read);
	pf_read = NULL;
}

📺效果展示

直接显示数据,就可以查看文件中的信息了

在这里插入图片描述

🚀完整代码

Contact.h头文件

#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<conio.h>
#include<Windows.h>

#define NAME_MAX 100
#define AGE_MAX 3
#define SEX_MAX 4
#define TEL_MAX 20
#define ADDR_MAX 40

//枚举功能
enum address_book
{
	Exit,
	Add,
	Delete,
	Find,
	Modify,
	Sort,
	Show,
	Save
};

//通讯录联系人信息
typedef struct Person
{
	char Name[NAME_MAX];
	char Age[AGE_MAX];
	char Gender[SEX_MAX];
	char Tel[TEL_MAX];
	char Address[ADDR_MAX];
}PeoInfo;



//顺序表结构体
typedef struct contact_seq_list
{
	PeoInfo* data;
	int capacity;//空间容量大小
	int size;//有效元素个数
}ConSL;



void init_contact(ConSL* con);//初始化函数

void load_contact(ConSL* con);//文件读操作函数

void save_contact(ConSL* con);//文件写操作函数

void addition_contact(ConSL* con);//添加函数

void delete_contact(ConSL* con);//删除函数

void show_contact(ConSL* con);//打印函数

void find_contact(ConSL* con);//查找函数

void modify_contact(ConSL* con);//修改函数

void sort_contact(ConSL* con);//排序函数

void save_contact(ConSL* con);//保存函数

void destroy_contact(ConSL* con);//销毁函数

Contact.c源文件

#define _CRT_SECURE_NO_WARNINGS 1

#include "Contact.h"

void check_capacity(ConSL* ptr);//声明一下

//文件读操作函数
void load_contact(ConSL* con)
{
	PeoInfo temp = { 0 };//临时变量
	assert(con);
	FILE* pf_read = fopen("contact_data.txt", "rb");
	if (pf_read == NULL)
	{
		perror("load_contact fopen error!\n");
		return;
	}
	//循环读取文件中的内容
	while (fread(&temp,sizeof(PeoInfo),1,pf_read))//返回0的时候就读取完了
	{
		check_capacity(con);
		con->data[con->size++] = temp;
	}

	fclose(pf_read);
	pf_read = NULL;
}


//文件写操作函数
void save_contact(ConSL* con)
{
	assert(con);
	FILE* pf_wirte = fopen("contact_data.txt", "wb");
	if (pf_wirte == NULL)
	{
		perror("save_contact fopen error!\n");
		return;
	}
	//写入 文件中
	for (int i = 0; i < con->size; i++)
	{
		fwrite(con->data+i, sizeof(PeoInfo), 1, pf_wirte);
	}
	printf("数据保存成功!\n");

	//关闭
	fclose(pf_wirte);
	pf_wirte = NULL;
}


//初始化函数
void init_contact(ConSL* con)
{
	con->data = NULL;
	con->capacity = con->size = 0;
	//文件加载
	load_contact(con);
}


void check_capacity(ConSL* ptr)
{
	if (ptr->capacity == ptr->size)
	{
		//说明空间为空或者满了,则需要扩容
		int new_capacity = ptr->capacity == 0 ? 4 : 2 * ptr->capacity;
		PeoInfo* temp = (PeoInfo*)realloc(ptr->data, new_capacity * sizeof(PeoInfo));
		if (temp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ptr->data = temp;
		ptr->capacity = new_capacity;
	}
}


//添加函数
void addition_contact(ConSL* con)
{
	assert(con);
	//添加时必须判断是否满
	check_capacity(con);
	//添加数据
	printf("联系人信息录入中……\n");
	printf("请输入姓名:");
	scanf("%s", con->data[con->size].Name);
	printf("请输入年龄:");
	scanf("%s", con->data[con->size].Age);
	printf("请输入性别:");
	scanf("%s", con->data[con->size].Gender);
	printf("请输入电话:");
	scanf("%s", con->data[con->size].Tel);
	printf("请输入地址:");
	scanf("%s", con->data[con->size].Address);

	//元素个数自增
	con->size++;
	printf("添加成功!\n");
}


//打印函数
void show_contact(ConSL* con)
{
	//assert(con.size);
	if (con->size == 0)
	{
		printf("通讯录为空,无法显示!\n");
		return;
	}
	printf("通讯录总人数:%d\n", con->size);
	printf("*************************************************************************************************\n");
	printf("*****************************          通讯录信息         ***************************************\n");
	printf("*************************************************************************************************\n");
	printf("-------------------------------------------------------------------------------------------------\n");
	printf("|%-12s\t%-3s\t%-4s\t%-12s\t\t%-40s|\n", "姓名", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("|%-12s\t%-3s\t%-4s\t%-12s\t\t%-40s|\n", con->data[i].Name
			, con->data[i].Age
			, con->data[i].Gender
			, con->data[i].Tel
			, con->data[i].Address);
	}
	printf("-------------------------------------------------------------------------------------------------\n");
}


static int find_information(ConSL* ptr,char* name)
{
	for (int i = 0; i < ptr->size; i++)
	{
		if (strcmp(ptr->data[i].Name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}


//删除函数
void delete_contact(ConSL* con)
{
	//assert(con&&con->size);
	assert(con);
	if (con->size == 0)
	{
		printf("通讯录为空,无法删除!\n");
		return;
	}
	printf("请输入要删除的联系人的姓名:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	int ret=find_information(con, name);
	if (ret == -1)
	{
		printf("没找到!\n");
		return;
	}
	for (int i = ret; i < con->size - 1; i++)
	{
		con->data[i] = con->data[i + 1];
	}
	con->size--;
	printf("删除成功!\n");
	show_contact(con);
}


//查找函数
void find_contact(ConSL* con)
{
	assert(con);
	if (con->size == 0)
	{
		printf("通讯录为空,无法查找!\n");
		return;
	}
	printf("请输入要查找的联系人的姓名:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	int ret=find_information(con, name);
	if (ret == -1)
	{
		printf("没查到!\n");
		return;
	}
	printf("-------------------------------------------------------------------------------------------------\n");
	printf("|%-12s\t%-3s\t%-4s\t%-12s\t\t%-40s|\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("|%-12s\t%-3s\t%-4s\t%-12s\t\t%-40s|\n", con->data[ret].Name
		, con->data[ret].Age
		, con->data[ret].Gender
		, con->data[ret].Tel
		, con->data[ret].Address);
	printf("-------------------------------------------------------------------------------------------------\n");
}


//修改函数
void modify_contact(ConSL* con)
{
	assert(con);
	if (con->size == 0)
	{
		printf("通讯录为空,无法修改!\n");
		return;
	}
	printf("请输入要修改的联系人的姓名:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	int ret = find_information(con, name);
	if (ret == -1)
	{
		printf("没找到,无法修改!\n");
		return;
	}
	printf("修改进行中………\n");
	printf("请输入新的姓名:");
	scanf("%s", con->data[ret].Name);
	printf("请输入新的年龄:");
	scanf("%s", con->data[ret].Age);
	printf("请输入新的性别:");
	scanf("%s", con->data[ret].Gender);
	printf("请输入新的电话:");
	scanf("%s", con->data[ret].Tel);
	printf("请输入新的地址:");
	scanf("%s", con->data[ret].Address);

	printf("修改成功!\n");
	show_contact(con);
}



int compar_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->Name, ((PeoInfo*)e2)->Name);
}

int compar_by_age(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->Age, ((PeoInfo*)e2)->Age);
}


//排序函数
void sort_contact(ConSL* con)
{
	assert(con);
	if (con->size == 0)
	{
		printf("通讯录为空,无法排序!\n");
		return;
	}

	printf("请选择排序方式:1、按照姓名排序,2、按照年龄排序。\n");
	int select1 = 0;
	scanf("%d", &select1);
	if (select1 == 1)
	{
		qsort(con->data, con->size, sizeof(PeoInfo), compar_by_name);
		printf("排序成功!\n");
	}
	if (select1 == 2)
	{
		qsort(con->data, con->size, sizeof(PeoInfo), compar_by_age);
		printf("排序成功!\n");
	}


}


//销毁函数
void destroy_contact(ConSL* con)
{
	if (con->data)
	{
		free(con->data);
	}
	con->data = NULL;
}

test_contact.c源文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"

void menu()
{
	printf("\t\t\t\t\t***************************************\n");
	printf("\t\t\t\t\t*********        通讯录       *********\n");
	printf("\t\t\t\t\t***************************************\n");
	printf("\t\t\t\t\t****  ——>  1、添加联系人  <——  ****\n");
	printf("\t\t\t\t\t***************************************\n");
	printf("\t\t\t\t\t****  ——>  2、删除联系人  <——  ****\n");
	printf("\t\t\t\t\t***************************************\n");
	printf("\t\t\t\t\t****  ——>  3、查找联系人  <——  ****\n");
	printf("\t\t\t\t\t***************************************\n");
	printf("\t\t\t\t\t****  ——>  4、修改联系人  <——  ****\n");
	printf("\t\t\t\t\t***************************************\n");
	printf("\t\t\t\t\t****  ——>  5、通讯录排序  <——  ****\n");
	printf("\t\t\t\t\t***************************************\n");
	printf("\t\t\t\t\t****  ——>  6、显示联系人  <——  ****\n");
	printf("\t\t\t\t\t***************************************\n");
	printf("\t\t\t\t\t****  ——>  7、保存联系人  <——  ****\n");
	printf("\t\t\t\t\t***************************************\n");
	printf("\t\t\t\t\t****  ——>  0、退出通讯录  <——  ****\n");
	printf("\t\t\t\t\t***************************************\n");

}


void test()
{
	ConSL con;
	init_contact(&con);
	int input = 0;
	while (1)
	{
		menu();
		printf("请选择功能:\n");
		scanf("%d", &input);
		switch (input)
		{
		case Exit:
			save_contact(&con);
			destroy_contact(&con);
			printf("欢迎下次使用!\n");
			exit(1);
		case Add:
			addition_contact(&con);
			break;
		case Delete:
			delete_contact(&con);
			break;
		case Find:
			find_contact(&con);
			break;
		case Modify:
			modify_contact(&con);
			break;
		case Sort:
			sort_contact(&con);
			break;
		case Show:
			show_contact(&con);
			break;
		case Save:
			save_contact(&con);
			break;
		default:
			printf("选择错误,请重新选择:\n");
			break;
		}
		_getch();
		system("cls");
	}
}

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

文件版本的通讯录到此为止。🤞
在这里插入图片描述

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值