[C language] file operation modify address book (upgrade version) can store data

We have learned the content of file operations above, so if you don’t understand, please read this article

[C language] Xiao Wang will take you to realize file operation (simple diagram explanation)_Xiao Wang's blog about learning code-CSDN blog

Address book We have also learned to implement static and dynamic address books before

[C language] Use C language to realize static and dynamic address book (simple and easy to understand) - Programmer Sought


Table of contents

foreword

1. Using file operation ideas

2. Use steps

1. Exit Retrofit

2. Initialize the transformation

3. Code demo

3. The complete code of the file operation address book

1.Contact.h

2.Contact.c

3.test.c

Summarize


foreword

When we implement static and dynamic databases, we will input a set of data, complete a series of additions, deletions, changes, and checks, the program will be closed, and when we open it next time, we will find that the previous data is gone. This is because our data They are all stored in memory. When the program ends, the natural memory is released, and it will be gone when it is opened again.

So, if the data in the program is transferred to the hard disk through file operations, can it be taken out next time?

Of course it is possible, we will show you how to do it.

1. Using file operation ideas

What do we want to change on the original address book?

1. Exit to save data        So when you enter 0 to exit, add file operations to save the data to the corresponding file

2. Open the program and extract the previous data.          When initializing, use file operations to

Modifying the above two points can improve the address book and realize the address book that can access data, which is more practical

2. Use steps

1. Exit Retrofit

as the picture shows:

code show as below:

void SaveContact(Contact* pc) {
	//存入数据
	//使用fwrite 二进制存储吧

	//fopen打开文件
	FILE* pf = fopen("Contact.txt", "wb");
	//判断是否存在文件Contact.txt
	if (NULL == pf) {
		perror("SaveContact::fopen");
	}
	else {
		fwrite(pc->data, sizeof(PeopleInfo), pc->sz, pf);
		//输出之后提示输出完成到Contact.txt中
		printf("保存完成\n");
		//关闭流 并pf置为NULL 防止野指针
		fclose(pf);
		pf = NULL;
	}

}

2. Initialize the transformation

We want to get the original data from the beginning. When we initialize, we can just read the data in the Contact.txt file.

The diagram is as follows:

code show as below:

//新增代码,读取文件中的数据
void read_Contact(Contact* pc) {
	//读取的时候先进行判断是否
	FILE* pf = fopen("Contact.txt", "r");
	if (NULL == pf) {
		perror("read_Contact::open");
	}
	else {
		PeopleInfo ptr={0};
		int i = 0;
		while (fread(&ptr, sizeof(PeopleInfo), 1, pf)) {
			check_capacity(pc);
			//不够就扩容
			pc->data[i] = ptr;
			pc->sz++;
			i++;
		}
	}
}
void check_capacity(Contact* pc) {
	if (pc->sz == pc->capacity) {
		//使用realloc函数 进行扩容
		PeopleInfo* ptr = (PeopleInfo*)realloc(pc->data, sizeof(PeopleInfo) * (pc->capacity + MAX2));
		if (ptr == NULL) {
			perror("check_capacity");
			return;
		}
		else {
			pc->data = ptr;
			pc->capacity = pc->capacity + MAX2;
			printf("扩容完成\n");
		}
	}
}
//这是动态通讯录的初始化
void InitContact(Contact* pc) {
	//进行初始化的时候,我们当然可以直接
	assert(pc);//断言
	pc->sz = 0;
	PeopleInfo *ptr=(PeopleInfo*)calloc(MAX1,sizeof(PeopleInfo));
	if (ptr == NULL) {
		perror("malloc::data");
		return;
	}
	pc->data = ptr;
	pc->capacity=MAX1;

	read_Contact(pc);
}

3. Code demo

As shown in the figure, in this way, it is possible to input and read data in the hard disk file, which is more suitable for actual needs. This is the dynamic address book after file operation and processing. Static is simpler. If you know dynamic, static can be realized.


3. The complete code of the file operation address book

We are divided into three parts, Contact.h Contact.c test.c

Contact.h declares the functions required by test.c as a header file

Contact.c implements the functions declared in Contact.h

test.c The body of the address book. The backbone implements the logic of the address book

1.Contact.h

#define _CRT_SECURE_NO_WARNINGS

//Contact 实现通讯录 头文件
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<malloc.h>
#include<stdlib.h>
#include<search.h>

#define MAX 100
#define NAME_MAX 20
#define SEX_MAX 5
#define ADDR_MAX 20
#define TELE_MAX 12


//下面两个define是用于动态通讯录的
#define MAX1 3	//表示第一次容积是多少
#define MAX2 2  //表示一次扩容多少




//构建通讯录所需的结构体
typedef struct PeopleInfo {
	char name[NAME_MAX];//姓名
	int age;//年龄
	char sex[NAME_MAX];//性别
	char addr[ADDR_MAX];//地址
	char tele[TELE_MAX];//电话号码
}PeopleInfo;

//这是静态通讯录  就是data这个数组是固定死的MAX
//typedef struct Contact {
//	PeopleInfo data[MAX];//表示存储的通讯录最大人员数
//	int sz;//表示当前Contact通讯录人员个数
//}Contact;

//实现动态通讯录
typedef struct Contact {
	PeopleInfo *data;//表示存储的通讯录最大人员数
	int sz;//表示当前Contact通讯录人员个数
	int capacity; //表示当前容量  作为扩容的依据
}Contact;

//初始化通讯录
void InitContact(Contact* pc);
//添加通讯录的信息
void addContact(Contact* pc);
//删除通讯录中的信息
void delContact(Contact* pc);
//查找通讯录成员信息
int searchContact(Contact* pc);
//打印
void showContact(Contact* pc);
//改变指定元素
void changeContact(Contact* pc);
//排序,按照名字排序
void sortContact(Contact* pc);

//保存通讯录
void SaveContact(Contact*pc);

//读取通讯录
void read_Contact(Contact*pc);

2.Contact.c

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
//用来实现头文件的代码
//
这是静态初始化
//void InitContact(Contact* pc) {
//	//进行初始化的时候,我们当然可以直接
//	pc->sz = 0;
//	memset(pc->data, 0, sizeof(pc->data));
//	//memset 函数  这样的话,从data这个数组的地址开始 sizeof(pc->data)个字节,都赋值为0
//}

//这是动态通讯录的初始化
void InitContact(Contact* pc) {
	//进行初始化的时候,我们当然可以直接
	assert(pc);//断言
	pc->sz = 0;
	PeopleInfo *ptr=(PeopleInfo*)calloc(MAX1,sizeof(PeopleInfo));
	if (ptr == NULL) {
		perror("malloc::data");
		return;
	}
	pc->data = ptr;
	pc->capacity=MAX1;

	read_Contact(pc);
}
静态通讯录
//void addContact(Contact* pc) {
//	assert(pc);
//	if (pc->sz == MAX) {
//		printf("通讯录已满,无法添加\n");
//		return;
//	}
//	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].addr);
//	printf("请输入电话:>");
//	scanf("%s", pc->data[pc->sz].tele);
//	printf("添加完成,请继续操作\n");
//	pc->sz++;
//}
//动态通讯录
void check_capacity(Contact* pc) {
	if (pc->sz == pc->capacity) {
		//使用realloc函数 进行扩容
		PeopleInfo* ptr = (PeopleInfo*)realloc(pc->data, sizeof(PeopleInfo) * (pc->capacity + MAX2));
		if (ptr == NULL) {
			perror("check_capacity");
			return;
		}
		else {
			pc->data = ptr;
			pc->capacity = pc->capacity + MAX2;
			printf("扩容完成\n");
		}
	}
}
	
void addContact(Contact* pc) {
	assert(pc);
	check_capacity(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].addr);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("添加完成,请继续操作\n");
	pc->sz++;
}
void delContact(Contact* pc) {
	assert(pc);
	printf("请选择删除的目标:>");
	if (pc->sz == 0) {
		return;
	}
	//删除的话只需要找到对应的要删除的数据,比如以名字为准,先找到,然后再讲其后面的元素覆盖前面的
	int pos = searchContact(pc);
	//换位置
	if (pos == -1) {
		printf("没有查找到该成员\n");
		return;
	}
	for (int i = pos; i < pc->sz - 1; i++) {
		pc->data[i] = pc->data[i + 1];
	}

	pc->sz--;//直接--不用管换位置之后最后一个数字的问题
	printf("删除完成\n");
}


int  searchContact(Contact* pc) {
	assert(pc);
	char name[20];
	int pos = -1;
	scanf("%s", name);
	//查询
	for (int i = 0; i < pc->sz; i++) {
		if (strcmp(pc->data[i].name, name) == 0) {
			pos = i;
		}
	}
	
	return pos;
}

void showContact(Contact* pc) {
	assert(pc);
	if (pc->sz == 0) {
		return;
	}//可以有可无
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
	for (int i = 0; i < pc->sz; i++) {
		printf("%-20s\t%-5d\t%-5s\t%-20s\t%-12s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);
	}
	printf("打印完成\n");
}



void changeContact(Contact* pc) {
	assert(pc);
	//先找到
	int pos = searchContact(pc);
	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].addr);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tele);
	printf("更改完成, 请继续操作\n");
}


void sortContact(Contact* pc) {
	assert(pc);
	if (pc->sz == 0) {
		printf("通讯录中暂无元素\n");
		return;
	}
	Contact s;
	InitContact(&s);
	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)==1) {
				s.data[j] = pc->data[j];
				pc->data[j] = pc->data[j + 1];
				pc->data[j + 1] = s.data[j];
			}
		}
	}
}

int compare(const void* e1, const void* e2) {
	return *((int*)e1) - *((int*)e2);
}
void sort(Contact*pc) {
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), compare);
}
//int main()
//
//{
//	qsort()
//	return 0;
//}

void SaveContact(Contact* pc) {
	//存入数据
	//使用fwrite 二进制存储吧

	//fopen打开文件
	FILE* pf = fopen("Contact.txt", "wb");
	//判断是否存在文件Contact.txt
	if (NULL == pf) {
		perror("SaveContact::fopen");
	}
	else {
		fwrite(pc->data, sizeof(PeopleInfo), pc->sz, pf);
		//输出之后提示输出完成到Contact.txt中
		printf("保存完成\n");
		//关闭流 并pf置为NULL 防止野指针
		fclose(pf);
		pf = NULL;
	}

}
void read_Contact(Contact* pc) {
	//读取的时候先进行判断是否
	FILE* pf = fopen("Contact.txt", "r");
	if (NULL == pf) {
		perror("read_Contact::open");
	}
	else {
		PeopleInfo ptr={0};
		int i = 0;
		while (fread(&ptr, sizeof(PeopleInfo), 1, pf)) {
			check_capacity(pc);
			//不够就扩容
			pc->data[i] = ptr;
			pc->sz++;
			i++;
		}
	}
}

3.test.c

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"

//这边进行主要的通讯录流程操作

void menu() {
	printf("***********************************************\n");
	printf("******      1.add           2.del        ******\n");
	printf("******      3.search        4.change     ******\n");
	printf("******      5.show          6.sort       ******\n");
	printf("******      0.exit                       ******\n");
	printf("***********************************************\n");

}
void test() {
	//打印选择菜单

	int input = 0;
	int pos = 0;
	Contact pc;
	//Contact pc={0};
	//当然可以这样初始化,但是不一定后来初始化都这样,所以有InitContact()
	InitContact(&pc);
	
	do {
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) {
			case 1:
				addContact(&pc);
				break;
			case 2:
				delContact(&pc);
				break;
			case 3:
				pos = searchContact(&pc);
				if (pos == -1) {
					printf("没有查找到该成员\n");
				}
				else {
					printf("%-20s\t%-5d\t%-5s\t%-20s\t%-12s\n", pc.data[pos].name, pc.data[pos].age, pc.data[pos].sex, pc.data[pos].addr, pc.data[pos].tele);
				}
				break;
			case 4:
				changeContact(&pc);
				break;
			case 5:
				showContact(&pc);
				break;
			case 6:
				sort(&pc);
				break;
			case 0:
				SaveContact(&pc);
				printf("退出通讯录\n");
				free(pc.data);
				break;
			default:
				break;
			}
	} while (input);
}
int main()
{
	test();
	return 0;
}

Summarize

This article realizes it through file operations. The data of the address book is stored on the hard disk, and the data can be read from the hard disk to the program, so this is more suitable for actual needs. We introduce the main file operations and applications, and The implementation method, and the complete code is attached, I hope friends can understand and understand such a program.

Xiao Wang is here to wish everyone a happy new year in the Year of the Rabbit in 2023! ! !

Guess you like

Origin blog.csdn.net/qq_63319459/article/details/128723542