C language implements address book (including file saving)

content

1. Test results

2. Overall idea

3. Definition of structure 

4. Core function construction

5. Interpretation of module code

(1), display menu

(2), initialize the address book

(3), increase the capacity of the address book

(4), add contacts

(5), find contacts

(6), delete contacts

(7), modify the contact

(8), sort the contacts in the address book by name

(9), display address book

(10), save the file

(11), load file information

(12), release space

6, the overall implementation of the code

  contact.h

  contact.c

  test.c


hello friends

Today, I will share with you an implementation of an address book, including pointers, structures, dynamic memory allocation, and file reading and writing. The article is a bit long. The complete address book code is at the end of the article. I hope you can read it patiently and gain something. Oh

1. Test results

This is the result of using this address book initially, there is no contact list in the file yet.

After exiting this program, we will find that there is a text file under the project path, which records the previous contact information. When the program is used again, the contact information saved in the file will be loaded again. Please see the image below:

The deletion, search, sorting, and modification of the contacts in it will not be demonstrated here, otherwise the screenshots will be too long  . Interested friends can take it and test it on their own compiler to see the effect. . So let's go straight to the topic now~

2. Overall idea

The overall style of the code is still the same as the three chess and minesweeper written before , or three files are built, or the implementation of each function is first put in the contact.c file, and then the header file contact.h Put these functions in Statement, so that contact.h can be directly referenced in the test.c file, and the functions in contact.c can be used, which can ensure that the main function logic is clear, concise, and easy to understand.

3. Definition of structure 

Because it is an address book, it is necessary to record each person's name, gender, age, address, phone number, etc., so I define a contact structure that contains various information about a person.

typedef struct PeoInfo
{
    char name[NAME_MAX];
    int age;
    char number[NUMBER_MAX];
    char adress[ADDR_MAX];
    char sex[SEX_MAX];
}PeoInfo;

 Then in order to facilitate the management of the information in the address book, I created a structure about the address book.

typedef struct Contact
{
	PeoInfo* data;//存放数据
	int capacity;//当前通讯录容量
	int sz;//实际有效信息数量
}Contact;

4. Core function construction

enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	SHOW
};
void menu()
{
	printf("***************菜单****************\n");
	printf("****** 1.add        2.del    ******\n");
	printf("****** 3.search     4.modify ******\n");
	printf("****** 5.sort       6.show   ******\n");
	printf("****** 0.exit                ******\n");
	printf("***********************************\n");


}
void test()
{
	Contact con;
	InitContact(&con);//初始化通讯录
	int input = 0;
	do
	{
		menu();
		printf("请选择->");
		scanf("%d", &input);
		switch (input)
		{
			case ADD:
				//增加联系人
				AddContact(&con);
				break;
			case DEL:
				//删除联系人
				DeleteContact(&con);
				break;
			case SEARCH:
				//查找联系人
				FindContact(&con);
				break;
			case MODIFY:
				//修改联系人
				ModifyContact(&con);
				break;
			case SORT:
				//对通讯录进行排序(按名字)
				SortContact(&con);
				break;
			case SHOW:
				//显示联系人
				ShowContact(&con);
				break;
			case EXIT:
				SaveContact(&con);
				DestroyContact(&con);
				printf("退出通讯录\n");
				break;
			default:
				printf("选择错误,请重新选择!\n");
				break;
		}
		
	}while (input);
}

 The do-while statement and switch statement are mainly used here to connect various functions in series to form a relatively complete project. Because the object of operation is the information in the address book, a variable con of the address book type is defined. Looking at this code, it should not be difficult to find that basically the parameters of every function are con. Each of the functions involved in it will be explained one by one below.

5. Interpretation of module code

(1), display menu

This is too simple, go directly to the code~

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

}

Don't worry, the various functions in the menu will be explained one by one later.

(2), initialize the address book

Because the address book does not have any information about the contact at first, we need to set its actual number of valid information to 0, and then apply for a PeoInfo-sized space to store the information. Initially, data is also the various information of the contact. Set to empty. The next step is to set the capacity of this address book. If the space application fails, an error message will be printed to facilitate later inspection and maintenance.

But if it is not the first time to use this program, the contact information recorded before will be automatically loaded when the program is started, which is convenient for viewing and modification. So I used file knowledge to write a function LoadContact() that loads information (don't worry

Its specific implementation will be described later), which is loaded during initialization.

void InitContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	PeoInfo *tmp = (PeoInfo*)malloc(DEFAULT_SZ *sizeof(PeoInfo));
	if (tmp != NULL)
	{
		pc->data = tmp;
	}
	else
	{
		printf("InitContact()::%s\n", strerror(errno));
		return;
	}
	pc->capacity = DEFAULT_SZ;
	LoadContact(pc);

}

(3), increase the capacity of the address book

This function is implemented using knowledge of dynamic memory management. Every time when the capacity capacity of the address book pc is equal to the actual number of valid information stored (the number of people stored in the address book), I need to increase the capacity of the address book so that subsequent contacts can be added. That is, use the realloc() function to change the capacity (memory) of the address book.

int  addcapacity(Contact* pc)
{
	assert(pc);
	if (pc->sz == pc->capacity)
	{
		PeoInfo* tmp = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo)*(pc->capacity+ 2));
		if (tmp != NULL)
		{
			pc->data = tmp;
			pc->capacity += 2;
			//printf("增容成功\n");
			return 1;
		}
		else
		{
			
			printf("addcapacity()::%s\n", strerror(errno));
			return 0;
		}
	}
	return 1;
	
}

(4), add contacts

The function AddContact() is used to add contacts. Calling this function means adding contact information to the address book. However, whenever adding contact information, it is necessary to make a judgment on the capacity of the address book. When the record is full, I will increase the capacity. Therefore, at the very beginning of the AddContact() function, I call a function I wrote. Its function is to determine whether the address book has been filled. If the capacity is not increased for the time being, 1 will be returned if the capacity increase is successful or if it is judged not to be increased, and 0 will be returned if the capacity increase fails. The contacts can be added to the address book only after it is judged that the capacity of the address book is sufficient or the capacity is successfully increased.

In fact, adding a contact is very simple, that is, assigning a value to the contact type data in the address book structure. Each time a contact is added, the actual number of valid information sz in the address book pc is increased by one.

void AddContact(Contact* pc)
{	
	assert(pc);
	int i=addcapacity(pc);
	if (i)
	{
		printf("请输入姓名->");
		scanf("%s", pc->data[pc->sz].name);
		printf("请输入性别->");
		scanf("%s", pc->data[pc->sz].sex);
		printf("请输入年龄->");
		scanf("%d", &(pc->data[pc->sz].age));
		printf("请输入住址->");
		scanf("%s", pc->data[pc->sz].adress);
		printf("请输入电话->");
		scanf("%s", pc->data[pc->sz].number);
		pc->sz++;
		printf("添加联系人成功!\n");
	}
	else
	{
		printf("AddContact::%s\n", strerror(errno));
	}
			
}

(5), find contacts

Contact information is stored in an array of contact type. Searching for a contact is actually equivalent to traversing the array. When the name of the contact to be searched is entered, the array will be traversed. Returns the index of the array if it is found, and -1 if it is not found.

int FindPeoInfo(char* name, Contact* pc)//查找联系人,返回其下标
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (*name == *(pc->data[i].name))
		{
			return i;
		}
	}
	return -1;
}

(6), delete contacts

Deleting a contact is actually to overwrite the deleted contact, and move the contact information behind the contact to be deleted forward in turn. Before deleting a contact, we need to find the array index corresponding to the contact, and then we need to call FindPeoInfo() function, and then move forward the next element of this element and the following elements in turn to cover. After the coverage is completed, the actual number of people with valid information sz in the address book is decremented by one.

void DeleteContact(Contact* pc)//删除联系人
{
	char name[NAME_MAX] = "0";
	int i = 0;
	printf("请输入要删除的联系人姓名->");
	scanf("%s", name);
	//查找联系人
	int flag=FindPeoInfo(name,pc);
	if (flag != -1)
	{
		for (i = flag; i < pc->sz-1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		pc->sz--;
		printf("删除成功!\n");
	}
	else
	{
		printf("没有找到您需要删除的人!\n");
	}
}

(7), modify the contact

Modifying a contact is to reassign the elements in the originally assigned contact type data array to achieve an effect of the change. Likewise, it is still necessary to call FindPeoInfo() to find the contact to be modified before modifying it.

void ModifyContact(Contact* pc)//修改联系人
{
	char name[NAME_MAX] = "0";
	printf("请输入要修改的联系人姓名->");
	scanf("%s", name);
	int flag = FindPeoInfo(name, pc);
	if (flag == -1)
	{
		printf("查无此人\n");
		return;
	}
	else
	{
		int input = 0;
		do
		{
			/*char rename[NAME_MAX] = "0";
			int reage = 0;
			char resex[] = "0";
			char readdress[] = "0";
			char*/
			printf("1.姓名  2.年龄  3.性别  4.住址  5.电话  0.退出\n");
			printf("请输入要修改的选项(按0退出修改)->");
			scanf("%d", &input);
			switch (input)
			{
				case 1:
				
					printf("请输入改正后的姓名->");
					scanf("%s", pc->data[flag].name);
					break;
				case 2:
					printf("请输入改正后的年龄->");
					scanf("%d", &(pc->data[flag].age));
					break;
				case 3:
					printf("请输入改正后的性别->");
					scanf("%s", pc->data[flag].sex);
					break;
				case 4:
					printf("请输入改正后的住址->");
					scanf("%s", pc->data[flag].adress);
					break;
				case 5:
					printf("请输入改正后的电话->");
					scanf("%s", pc->data[flag].number);
					break;
				case 0:
					break;
				default:
					printf("输入错误,请重新输入!\n");
					break;
			}
		} while(input);
		printf("修改成功!\n");
	}

}

 (8), sort the contacts in the address book by name

This is also very simple, just call the qsort() function to sort the string name in the structure type. I won't go into too much detail, just look at the code~

//对联系人进行排序(按名字)
int compare_Peo(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name,((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), compare_Peo);
	printf("排序成功\n");
	ShowContact(pc);
}

(9), display address book

The implementation of this function is to first determine whether the actual number of valid information in the address book is 0. If it is 0, it means that there is no one in the address book. If it is not 0, it traverses the data array of the contact type and prints them one by one.

void ShowContact(Contact* pc)//显示通讯录
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录里无联系人!\n");
	}
	else
	{
		int i = 0;
		printf("%-7s\t%-7s\t%-6s\t%-20s\t%-15s\n", "姓名", "性别", "年龄", "住址", "电话");
		for (i = 0; i < pc->sz; i++)
		{
			printf("%-7s\t%-7s\t%-6d\t%-20s\t%-15s\n",
				pc->data[i].name, pc->data[i].sex, pc->data[i].age,
				pc->data[i].adress, pc->data[i].number);
		}
	}
}

(10), save the file

The function of this function is to write the modification of the information in the address book into a file in binary form, and save it to the path of this project, which is convenient for viewing when the program is started next time.

//保存文件
void SaveContact(Contact* pc)
{
	FILE* fp = fopen("contact1.txt", "wb");
	if (fp == NULL)
	{
		printf("SaveContact::open for writting:%s", strerror(errno));
		return;
	}
	//写入文件
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, fp);
	}
	//关闭文件
	fclose(fp);
	fp = NULL;
}

 (11), load file information

When starting this program, we need to initialize the address book first (this step has been mentioned above), and then load the previously saved contact information, so that it is convenient to use this program for the previous contact information. Modified view. Reading file information is also equivalent to adding contacts, so before reading in, you also need to judge the capacity of the address book to see if it needs to be increased.

void LoadContact(Contact* pc)
{
	
	//打开文件
	FILE* pf = fopen("contact1.txt", "rb");
	if (pf == NULL)
	{
		printf("LoadContact::open for reading:%s\n", strerror(errno));
		return;
	}
	//读文件
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		addcapacity(pc);
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}

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

(12), release space

Because the space of the contact type array in the address book is dynamically applied, when we end this program, we first use the SaveContact() function to save the contact information, and then release this space, and will point to the pointer to this space. Set to NULL to avoid illegal access.

void DestroyContact(Contact* pc)//销毁
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

6, the overall implementation of the code

contact.h

#define _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h> 
//#define MAX_SIZE 10
#define NAME_MAX 20
#define SEX_MAX 5
#define ADDR_MAX 30
#define NUMBER_MAX 12
#define DEFAULT_SZ 3


typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char number[NUMBER_MAX];
	char adress[ADDR_MAX];
	char sex[SEX_MAX];
}PeoInfo;

typedef struct Contact
{
	PeoInfo* data;//存放数据
	int capacity;//当前通讯录容量
	int sz;//实际有效信息数量
}Contact;

void InitContact(Contact* pc);//初始化通讯录
void AddContact(Contact* pc);//增加联系人
void ShowContact(Contact* pc);//显示通讯录
void DeleteContact(Contact* pc);//删除联系人
int FindPeoInfo(char* name, Contact* pc);//查找联系人,返回其下标
void FindContact(Contact* pc);//查找联系人
void ModifyContact(Contact* pc);//修改联系人
void SortContact(Contact* pc);//对联系人进行排序(按名字)
int addcapacity(Contact* pc);//增容
void DestroyContact(Contact* pc);//销毁通讯录
void LoadContact(Contact* pc);//加载通讯录
void SaveContact(Contact* pc);//保存通讯录


contact.c

#include"contact.h"

//初始化通讯录
void InitContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	PeoInfo *tmp = (PeoInfo*)malloc(DEFAULT_SZ *sizeof(PeoInfo));
	if (tmp != NULL)
	{
		pc->data = tmp;
	}
	else
	{
		printf("InitContact()::%s\n", strerror(errno));
		return;
	}
	pc->capacity = DEFAULT_SZ;
	LoadContact(pc);

}
//判断是否增容
int  addcapacity(Contact* pc)
{
	assert(pc);
	if (pc->sz == pc->capacity)
	{
		PeoInfo* tmp = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo)*(pc->capacity+ 2));
		if (tmp != NULL)
		{
			pc->data = tmp;
			pc->capacity += 2;
			//printf("增容成功\n");
			return 1;
		}
		else
		{
			
			printf("addcapacity()::%s\n", strerror(errno));
			return 0;
		}
	}
	return 1;
	
}
//加载文件
void LoadContact(Contact* pc)
{
	
	//打开文件
	FILE* pf = fopen("contact1.txt", "rb");
	if (pf == NULL)
	{
		printf("LoadContact::open for reading:%s\n", strerror(errno));
		return;
	}
	//读文件
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		addcapacity(pc);
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}

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

//增加联系人
void AddContact(Contact* pc)
{	
	assert(pc);
	int i=addcapacity(pc);
	if (i)
	{
		printf("请输入姓名->");
		scanf("%s", pc->data[pc->sz].name);
		printf("请输入性别->");
		scanf("%s", pc->data[pc->sz].sex);
		printf("请输入年龄->");
		scanf("%d", &(pc->data[pc->sz].age));
		printf("请输入住址->");
		scanf("%s", pc->data[pc->sz].adress);
		printf("请输入电话->");
		scanf("%s", pc->data[pc->sz].number);
		pc->sz++;
		printf("添加联系人成功!\n");
	}
	else
	{
		printf("AddContact::%s\n", strerror(errno));
	}
	
	
	

	
}
void ShowContact(Contact* pc)//显示通讯录
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录里无联系人!\n");
	}
	else
	{
		int i = 0;
		printf("%-7s\t%-7s\t%-6s\t%-20s\t%-15s\n", "姓名", "性别", "年龄", "住址", "电话");
		for (i = 0; i < pc->sz; i++)
		{
			printf("%-7s\t%-7s\t%-6d\t%-20s\t%-15s\n",
				pc->data[i].name, pc->data[i].sex, pc->data[i].age,
				pc->data[i].adress, pc->data[i].number);
		}
	}
}
int FindPeoInfo(char* name, Contact* pc)//查找联系人,返回其下标
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (*name == *(pc->data[i].name))
		{
			return i;
		}
	}
	return -1;
}

void DeleteContact(Contact* pc)//删除联系人
{
	char name[NAME_MAX] = "0";
	int i = 0;
	printf("请输入要删除的联系人姓名->");
	scanf("%s", name);
	//查找联系人
	int flag=FindPeoInfo(name,pc);
	if (flag != -1)
	{
		for (i = flag; i < pc->sz-1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		pc->sz--;
		printf("删除成功!\n");
	}
	else
	{
		printf("没有找到您需要删除的人!\n");
	}
}
void FindContact(Contact* pc)//查找联系人
{
	char name[NAME_MAX] = "0";
	printf("请输入要查找的联系人姓名->");
	scanf("%s", name);
	int flag = FindPeoInfo(name, pc);
	if (flag != -1)
	{
		printf("%-7s\t%-7s\t%-6s\t%-20s\t%-15s\n", "姓名", "性别", "年龄", "住址", "电话");

		printf("%-7s\t%-7s\t%-6d\t%-20s\t%-15s\n",
			pc->data[flag].name, pc->data[flag].sex, pc->data[flag].age,
			pc->data[flag].adress, pc->data[flag].number);
	}
	else
	{
		printf("查无此人!\n");
	}
}

void ModifyContact(Contact* pc)//修改联系人
{
	char name[NAME_MAX] = "0";
	printf("请输入要修改的联系人姓名->");
	scanf("%s", name);
	int flag = FindPeoInfo(name, pc);
	if (flag == -1)
	{
		printf("查无此人\n");
		return;
	}
	else
	{
		int input = 0;
		do
		{
			/*char rename[NAME_MAX] = "0";
			int reage = 0;
			char resex[] = "0";
			char readdress[] = "0";
			char*/
			printf("1.姓名  2.年龄  3.性别  4.住址  5.电话  0.退出\n");
			printf("请输入要修改的选项(按0退出修改)->");
			scanf("%d", &input);
			switch (input)
			{
				case 1:
				
					printf("请输入改正后的姓名->");
					scanf("%s", pc->data[flag].name);
					break;
				case 2:
					printf("请输入改正后的年龄->");
					scanf("%d", &(pc->data[flag].age));
					break;
				case 3:
					printf("请输入改正后的性别->");
					scanf("%s", pc->data[flag].sex);
					break;
				case 4:
					printf("请输入改正后的住址->");
					scanf("%s", pc->data[flag].adress);
					break;
				case 5:
					printf("请输入改正后的电话->");
					scanf("%s", pc->data[flag].number);
					break;
				case 0:
					break;
				default:
					printf("输入错误,请重新输入!\n");
					break;
			}
		} while(input);
		printf("修改成功!\n");
	}

}

//对联系人进行排序(按名字)
int compare_Peo(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name,((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), compare_Peo);
	printf("排序成功\n");
	ShowContact(pc);
}
void DestroyContact(Contact* pc)//空间销毁
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}
//保存文件
void SaveContact(Contact* pc)
{
	FILE* fp = fopen("contact1.txt", "wb");
	if (fp == NULL)
	{
		printf("SaveContact::open for writting:%s", strerror(errno));
		return;
	}
	//写入文件
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, fp);
	}
	//关闭文件
	fclose(fp);
	fp = NULL;
}

test.c

#include"contact.h"
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	SHOW
};
void menu()
{
	printf("***************菜单****************\n");
	printf("****** 1.add        2.del    ******\n");
	printf("****** 3.search     4.modify ******\n");
	printf("****** 5.sort       6.show   ******\n");
	printf("****** 0.exit                ******\n");
	printf("***********************************\n");


}
void test()
{
	Contact con;
	InitContact(&con);//初始化通讯录
	int input = 0;
	do
	{
		menu();
		printf("请选择->");
		scanf("%d", &input);
		switch (input)
		{
			case ADD:
				//增加联系人
				AddContact(&con);
				break;
			case DEL:
				//删除联系人
				DeleteContact(&con);
				break;
			case SEARCH:
				//查找联系人
				FindContact(&con);
				break;
			case MODIFY:
				//修改联系人
				ModifyContact(&con);
				break;
			case SORT:
				//对通讯录进行排序(按名字)
				SortContact(&con);
				break;
			case SHOW:
				//显示联系人
				ShowContact(&con);
				break;
			case EXIT:
				SaveContact(&con);
				DestroyContact(&con);
				printf("退出通讯录\n");
				break;
			default:
				printf("选择错误,请重新选择!\n");
				break;
		}
		
	}while (input);
}



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

That's it for sharing. How about it? Is it very simple? Friends who have questions or don't understand can ask me, if you find any

If you have any problems or can be improved, you can also submit them in the comment area or private chat. I really hope to receive your suggestions.

Guess you like

Origin blog.csdn.net/m0_63039919/article/details/123183832