C language address book (dynamic storage file version)

Table of contents

 foreword

1. Basic ideas

 2. Implementation of the code

  2.1 Address book menu

 2.2 Definition and function of address book

 2.3 Function implementation 

 2.3.1 Initialize address book     

 2.3.2 Transfer file information to address book

 2.3.3 Expand address book

 2.3.4 Add contacts 

2.3.5 Delete contacts

2.3.6 Query contacts

2.3.7 Modify Contacts

2.3.8 Print address book

2.3.9 Information retained in files

 2.3.10 Destroy the space and exit the program

3. Complete code

 3.1Text.c file

3.2Contact.h file

3.3Contact.c file

Summarize


 foreword

The address book of the file storage version adds file operations on the basis of the address book. Before  understanding
the address book (file storage version), we have to learn about   file operations
. Only after mastering the operation file can we understand the address book of the file storage version.

1. Basic ideas

       1. The address book is composed of multiple people's information, information: name, age, gender, address, etc.

       2. The size of the address book and the number of people stored, this uses dynamic storage, which is more convenient for storage and space utilization.

       3. The basic functions of the address book: add contacts, delete contacts, find contacts, modify contacts

       4. Save the address book file for the convenience of next use.

   Note: There are three types of address book: static, dynamic, and file . And this article is about the dynamically stored file version of the address book .

           Static : The size is fixed, and the number of people stored is clearly limited and cannot be changed. It is implemented using an array.

           Dynamic : The number of people stored can be adjusted, and can increase with the increase of the number of people. Select an initial size, and then expand the operation to make better use of space.

           File : This address book is an operation of adding a storage file to one of the above two address books. It cannot be saved after the program is executed, and the entered information will disappear when the program ends. In order to save the entered information, it can be realized through file operations .

 2. Implementation of the code

  2.1 Address book menu

                  Menus enable interaction with users. You need to choose the functions of adding, deleting, checking, and modifying .

                 Therefore, the address book needs a menu.

                code show as below:

void menu()
{
	printf("*********************************\n");
	printf("*******1.添加        2.删除*******\n");
	printf("*******3.查找        4.修改*******\n");
	printf("*******5.显示        6.保存*******\n");
	printf("*******0.退出              *******\n");
	printf("*********************************\n");
}
//使用函数指针数组
void (*(p[7]))(Contact*) = { Exit,AddContact,DeleteContact,SearchContact,ModifyContact,PrintContact,SaveContact };


int main()
{ 
    //Contact cl;    这是下面代码结构体的
    //InitContact(&cl);
    int input;
	do {
		menu();
		printf("请输入->");
		scanf("%d", &input);
		if (input <= 6)
			p[input](&cl);  
		else
			printf("输入错误\n");
      
	}while (input != 0);
}

 For convenience, we use an array of function pointers , void (*(p[7]))(Contact*)   

 2.2 Definition and function of address book

                    The address book needs name, gender, age, and phone number . At this time, we need to use a structure to define it. Also need to define functions: add, delete, check, modify, print student information, save address book.

             code show as below:

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
typedef struct PeoInfo
{
	char name[10];//姓名
	int age;      //年龄
	char sex[3];  //性别
	int phone[12];//电话
}PeoInfo;

typedef struct Contact
{	
	int size;  //当前存储的人数
	int capacity;  //通讯录容量大小
	contact* data;  //结构体指针,访问个人信息

}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//删除联系人
void DeleteContact(Contact* pc);
//查找联系人
void SearchContact(Contact* pc);
//修改联系人
void ModifyContact(Contact* pc);
//显示通讯录
void PrintContact(Contact* pc);
//扩容通讯录
void CheckCapacity(Contact* pc);
//保存信息到文件
void SaveContact(Contact* pc);
//文件信息传递到通讯录
void LoadContact(Contact* pc);
//销毁空间,退出程序
void Exit(Contact* pc);


 2.3 Function implementation 

Note: When the address book exits, write the information to the file.
       After the address book is initialized, load the information of the file into the address book.

 2.3.1 Initialize address book     

              The address book is dynamic, so it needs to be expanded and given a certain amount of space.


void InitContact(Contact* pc)
{
	// 此时通讯录是空的,应先为通讯录分配空间
	pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * 4);

	// 如果分配成功,将通讯录的size设为0,capacity设为初识大小
	pc->size = 0;
	pc->capacity = 4;
	//将文档的信息传递到动态内存里,函数实现在下方
	LoadContact(pc);
}

 2.3.2 Transfer file information to address book

Load the file information into the address book

void LoadContact(Contact* pc)
{
	// 以读的形式打开文件
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}

	// 将文件中的内容加载到通讯录中
	// 这里用fread函数,当fread函数读取的联系人信息数为0时,说明读取结束
	PeoInfo tmp = { 0 }; // 定义一个联系人信息的结构体,便于读取
	int i = 0;
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		CheckCapacity(pc); // 在这个函数中查看数组是否需要扩容,若需要,则扩容
		pc->data[i] = tmp;
		pc->size++;
		i++;
	}

	// 关闭文件
	fclose(pf);
	pf = NULL;
	return;
}

 2.3.3 Expand address book

        Before adding contacts, it is necessary to determine whether the address book is full, and if it is full, it needs to be expanded

void CheckCapacity(Contact* pc)
{
	// 判断通讯录是否已满,若满,进行扩容
	if (pc->size == pc->capacity)
	{
		PeoInfo* tmp = (PeoInfo*)realloc(pc, sizeof(PeoInfo) * 4);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			return;
		}
		pc->data = tmp;

		// 若扩容成功,增大capacity
		pc->capacity *= 2;
	}

}

 2.3.4 Add contacts 

            Information about the contact needs to be added.

void AddContact(Contact* pc)
{
	int num = 0;
	printf("添加人数:");
	scanf("%d", &num);
	// 输入要添加的联系人的信息
	// 这里pc->data为结构体数组,pc->data[pc->size]为其中的元素,也就是某一个联系人的信息
	for (int i = 0; i < num; i++)
	{
		//判断通讯录是否满人
		CheckCapacity(pc);
		printf("请输入名字\n");
		scanf("%s", pc->data[pc->size].name);
		printf("请输入性别\n");
		scanf("%s", pc->data[pc->size].sex);
		printf("请输入年龄\n");
		scanf("%d", &pc->data[pc->size].age);
		printf("请输入电话\n");
		scanf("%s", pc->data[pc->size].phone);
		

		pc->size++; // 将存入的联系人的数量加1
	}
}

2.3.5 Delete contacts

      It is necessary to find the subscript value of the contact, and then delete it.


void DeleteContact(Contact* pc)
{
	int ret = 0;//记录寻找的下标值
	printf("请输入要删除的联系人的名字\n");
	char name[20];
	scanf("%s", name);
	// 定义一个新函数find,用来查找是否有这个联系人
	// 如果有,返回联系人的下标,如果没有,返回-1
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			ret = i; break;
		}
	}
	if (ret)
	{
		printf("不存在");
	}
	else {

		for (int i = ret; i < pc->size - 1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		pc->size--;
	}


}

2.3.6 Query contacts

Find the subscript value to get the contact information

void SearchContact(Contact* pc)
{
	int ret = 0;
	printf("请输入要查找的联系人的名字\n");
	char name[20];
	scanf("%s", name);
	// 利用已经定义的find函数进行查找
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			ret = i; break;
		}
	}

	if (ret)
	{
		printf("没有找到该联系人\n");
	}
	else
	{
		// 如果找到,打印该联系人的信息,首先打印五个标题
		printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");
		printf("%-10s\t%-10s\t%-5d\t%-15s%\n",
			pc->data[ret].name,
			pc->data[ret].sex,
			pc->data[ret].age,
			pc->data[ret].phone
			);
	}


}

2.3.7 Modify Contacts

Find the subscript value, so as to modify the data

void ModifyContact(Contact* pc)
{
	int ret = 0;
	printf("请输入要查找的联系人的名字\n");
	char name[20];
	scanf("%s", name);
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			ret = i; break;
		}
	}

	if (ret)
	{
		printf("没有找到该联系人\n");
	}
	else
	{
		printf("请输入名字\n");
		scanf("%s", pc->data[ret].name);
		printf("请输入性别\n");
		scanf("%s", pc->data[ret].sex);
		printf("请输入年龄\n");
		scanf("%d", &pc->data[ret].age);
		printf("请输入电话\n");
		scanf("%s", pc->data[ret].phone);
	
	}


}

2.3.8 Print address book

Print the specific data of each person

// 在这个函数内打印所有联系人的信息
void PrintContact(Contact* pc)
{
	// 首先打印五个标题
	printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");
	// 然后用for循环打印所有联系人的信息
	for (int i = 0; i < pc->size; i++)
	{
		printf("%-10s\t%-10s\t%-5d\t%-15s\n",
			pc->data[i].name,
			pc->data[i].sex,
			pc->data[i].age,
			pc->data[i].phone	
		);
	}
}

2.3.9 Information retained in files

When the program exits, the space must be destroyed and the data stored in the file for the convenience of the next call

void SaveContact(Contact* pc)
{
	FILE* p = fopen("contact.txt", "wb");
	if (p == NULL)
	{
		perror("SaveContact");
	}
	else {
		int i = 0;
		for (i; i < pc->size; i++)
		{
			fwrite(pc->data + i, sizeof(PeoInfo), 1, p);
		}

		fclose(p);
		p = NULL;
		printf("保存成功");
	}
	
}

 2.3.10 Destroy the space and exit the program

void Exit(Contact* pc)
{
	//销毁空间
	free(pc->data);
	pc->data = NULL;
	pc->size = 0;
	pc->capacity = 0;
}

3. Complete code

Compared with the above code, the implementation of each function of Contact.c is coherent.

 3.1Text.c file

#include"Contact.h"
void menu()
{
	printf("*********************************\n");
	printf("*******1.添加        2.删除*******\n");
	printf("*******3.查找        4.修改*******\n");
	printf("*******5.显示        6.保存*******\n");
	printf("*******0.退出              *******\n");
	printf("*********************************\n");
}
//使用函数指针数组
void (*(p[7]))(Contact*) = { Exit,AddContact,DeleteContact,SearchContact,ModifyContact,PrintContact,SaveContact };

int main()
{
	//定义结构体
	Contact cl;
	InitContact(&cl);
	int input;
	do {
		menu();
		printf("请输入->");
		scanf("%d", &input);
		if (input <= 6)
			p[input](&cl);
		else
			printf("输入错误\n");

	} while (input != 0);
}

3.2Contact.h file

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
typedef struct PeoInfo
{
	char name[10];//姓名
	int age;      //年龄
	char sex[3];  //性别
	int phone[12];//电话
}PeoInfo;

typedef struct Contact
{
	int size;  //当前存储的人数
	int capacity;  //通讯录容量大小
	PeoInfo* data;  //结构体指针,访问个人信息

}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//删除联系人
void DeleteContact(Contact* pc);
//查找联系人
void SearchContact(Contact* pc);
//修改联系人
void ModifyContact(Contact* pc);
//显示通讯录
void PrintContact(Contact* pc);
//扩容通讯录
void CheckCapacity(Contact* pc);
//销毁并且保存通讯录
void SaveContact(Contact* pc);
void LoadContact(Contact* pc);
void Exit(Contact* pc);

3.3Contact.c file

#include"Contact.h"

void InitContact(Contact* pc)
{
	// 此时通讯录是空的,应先为通讯录分配空间
	pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * 4);

	// 如果分配成功,将通讯录的size设为0,capacity设为初识大小
	pc->size = 0;
	pc->capacity = 4;
	//将文档的信息传递到动态内存里,函数实现在下方
	LoadContact(pc);
}
void LoadContact(Contact* pc)
{
	// 以读的形式打开文件
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}

	// 将文件中的内容加载到通讯录中
	// 这里用fread函数,当fread函数读取的联系人信息数为0时,说明读取结束
	PeoInfo tmp = { 0 }; // 定义一个联系人信息的结构体,便于读取
	int i = 0;
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		CheckCapacity(pc); // 在这个函数中查看数组是否需要扩容,若需要,则扩容
		pc->data[i] = tmp;
		pc->size++;
		i++;
	}

	// 关闭文件
	fclose(pf);
	pf = NULL;
	return;
}
void CheckCapacity(Contact* pc)
{
	// 判断通讯录是否已满,若满,进行扩容
	if (pc->size == pc->capacity)
	{
		PeoInfo* tmp = (PeoInfo*)realloc(pc, sizeof(PeoInfo) * 4);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			return;
		}
		pc->data = tmp;

		// 若扩容成功,增大capacity
		pc->capacity *= 2;
	}

}
void AddContact(Contact* pc)
{
	int num = 0;
	printf("添加人数:");
	scanf("%d", &num);
	// 输入要添加的联系人的信息
	// 这里pc->data为结构体数组,pc->data[pc->size]为其中的元素,也就是某一个联系人的信息
	for (int i = 0; i < num; i++)
	{
		//判断通讯录是否满人
		CheckCapacity(pc);
		printf("请输入名字\n");
		scanf("%s", pc->data[pc->size].name);
		printf("请输入性别\n");
		scanf("%s", pc->data[pc->size].sex);
		printf("请输入年龄\n");
		scanf("%d", &pc->data[pc->size].age);
		printf("请输入电话\n");
		scanf("%s", pc->data[pc->size].phone);
		

		pc->size++; // 将存入的联系人的数量加1
	}
}
void DeleteContact(Contact* pc)
{
	int ret = 0;//记录寻找的下标值
	printf("请输入要删除的联系人的名字\n");
	char name[20];
	scanf("%s", name);
	// 定义一个新函数find,用来查找是否有这个联系人
	// 如果有,返回联系人的下标,如果没有,返回-1
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			ret = i; break;
		}
	}
	if (ret)
	{
		printf("不存在");
	}
	else {

		for (int i = ret; i < pc->size - 1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		pc->size--;
	}


}
void SearchContact(Contact* pc)
{
	int ret = 0;
	printf("请输入要查找的联系人的名字\n");
	char name[20];
	scanf("%s", name);
	// 利用已经定义的find函数进行查找
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			ret = i; break;
		}
	}

	if (ret)
	{
		printf("没有找到该联系人\n");
	}
	else
	{
		// 如果找到,打印该联系人的信息,首先打印五个标题
		printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");
		printf("%-10s\t%-10s\t%-5d\t%-15s%\n",
			pc->data[ret].name,
			pc->data[ret].sex,
			pc->data[ret].age,
			pc->data[ret].phone
			);
	}


}
void ModifyContact(Contact* pc)
{
	int ret = 0;
	printf("请输入要查找的联系人的名字\n");
	char name[20];
	scanf("%s", name);
	// 利用已经定义的find函数进行查找
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			ret = i; break;
		}
	}

	if (ret)
	{
		printf("没有找到该联系人\n");
	}
	else
	{
		printf("请输入名字\n");
		scanf("%s", pc->data[ret].name);
		printf("请输入性别\n");
		scanf("%s", pc->data[ret].sex);
		printf("请输入年龄\n");
		scanf("%d", &pc->data[ret].age);
		printf("请输入电话\n");
		scanf("%s", pc->data[ret].phone);
	
	}


}
// 在这个函数内打印所有联系人的信息
void PrintContact(Contact* pc)
{
	// 首先打印五个标题
	printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");
	// 然后用for循环打印所有联系人的信息
	for (int i = 0; i < pc->size; i++)
	{
		printf("%-10s\t%-10s\t%-5d\t%-15s\n",
			pc->data[i].name,
			pc->data[i].sex,
			pc->data[i].age,
			pc->data[i].phone	
		);
	}
}
void SaveContact(Contact* pc)
{
	FILE* p = fopen("contact.txt", "wb");
	if (p == NULL)
	{
		perror("SaveContact");
	}
	else {
		int i = 0;
		for (i; i < pc->size; i++)
		{
			fwrite(pc->data + i, sizeof(PeoInfo), 1, p);
		}

		fclose(p);
		p = NULL;
		printf("保存成功");
	}
	
}
void Exit(Contact* pc)
{
	//销毁空间
	free(pc->data);
	pc->data = NULL;
	pc->size = 0;
	pc->capacity = 0;
}

Summarize

         When writing a dynamic storage file version of the address book, we have to learn dynamic storage and file operations .

         Only by constantly mastering knowledge, can we type codes handily, and gradually improve in continuous learning.

                                                                                                      ------------- Side dish TQ02

Guess you like

Origin blog.csdn.net/m0_74097410/article/details/129207554