⭐ C language small project ⭐ Address book (ten thousand word tutorial / static & dynamic & file operation for you / with source code / really don't you collect it?!)

Keywords: C

catalogue

preface

Problem description

tool

Basic framework

Static address book

Specific implementation ideas and processes

Preparation stage

Create contact information and address book structure

subject

Menu interface

Realization of various functions of address book

Initialize address book (empty address book contacts)

Add contacts

Delete address book contact

Find contacts in contacts

Modify contact information

Show contacts

Sort address book contacts

Overall effect drawing

Attach the source code

Dynamic address book

Address book structure

Initialize address book

Address book capacity increase

Address book destruction

Data saving

output data

Input data (load data)

Attach the source code

preface

The best way to test learning results is practice

After learning the basic knowledge of C language, you can easily realize some small projects

This article is a hand-in-hand explanation of the implementation of C language static address book (take a good look, I believe it will not be too difficult to say)

When you finish it, you will have a sense of achievement and happiness!!

Note: hands on teaching is very practical!!!

Problem description

Using C language to realize simple address book

tool

vs2019

Basic framework

The address book can be used to store the information of 100 people. Each person's information includes: name, gender, age, telephone and address

  • Provide method:
  1. Add contact information
  2. Delete specified contact information
  3. Find specified contact information
  4. Modify the specified contact information
  5. Show all contact information
  6. Empty all contacts
  7. Sort all contacts by name

Static address book

  Rely on arrays and structures to achieve (more basic)

Specific implementation ideas and processes

Note: some parts of the reference code can be optimized according to your own needs

Preparation stage

  • You need to create two source files and a header file:
  1. contact.h: macro definition modifies specific data (convenient for maintenance), including various header files, and declarations of structures and functions
  2. test.c: the overall process and logic of writing address book
  3. contact.c: realize various functions of the address book

Create contact information and address book structure

  • For contact information:

It shall include name, gender, age, telephone number and address

  • For static contacts:

In addition to the contact person, the number of users also needs to be recorded (to facilitate the implementation of later functions)

Therefore, we need to create structure variables

  • Reference code:
//Personal information structure
struct Peoinfo 
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	int number[NUMBER_MAX];
	char addr[ADDR_MAX];
};

//Address book structure
struct Contact
{
	//Total contact capacity
	struct Peoinfo data[PEOINFO_MAX];
	//Number of records used
	int sz;
};

In order to facilitate future maintenance and modification, we can modify some data with preprocessing instructions

  • Reference code:
//Maximum number of messages received (preprocessing instructions for easy maintenance)
#define NAME_MAX 20
#define NUMBER_MAX 11
#define SEX_MAX  10
#define ADDR_MAX 30

#define PEOINFO_MAX 100

subject

  • do while loop:

First, enter the selection function or exit. After selecting the function, you can continue to select. Therefore, the do while loop is used to realize the overall logic

  • Callback function:

For the implementation of various functions, you generally only need to pass in the structure address to operate the address book, so the parameter forms are consistent and the return types are consistent. Therefore, the callback function is easy to call the function, and it is simple and convenient

  • Compass:

An array whose elements are function pointers (convenient for passing in function addresses)

  • Reference code:
//The callback function needs to pass in the function address (calling function) and address book address (operating address book)
void Calo(void(*pc)(struct Peoinfo*i), struct Contact* p)
{
	pc(p);//pc() is a function call, and the parameter passed in p is the address book address
}
//Subject logic
int main()
{
	int intput;
	struct Contact con;//Create an address book
	InitContact(&con);//Initialize address book
	//Write a compass array, the element is a function pointer (convenient for calling functions and passing parameters)
	void(*table[8])(struct Contract* pc) = { 0,AddContact,DelContact,SearchContact,ModifyContact,ShowContact,SortContact,InitContact };
	//Basic logic loop
	do 
	{
		menu();
		printf("Please enter what you want to do next:->\n");
		scanf("%d", &intput);
		if (intput > 0 && intput <=7 )
		{
			printf("Successfully entered the selected operation!\n");
			Calo(table[intput],&con);//Callback operation
		}
		else if (intput == 0)
		{
			printf("Exit operation succeeded!!\n");
			break;
		}
		else
		{
			printf("Input error! Please reselect:->\n");
		}
	} while (intput);//Exit if intput is 0
}

Menu interface

This is very simple, directly on the code

  • Reference code:
void menu()
{
	printf("**************************\n");
	printf("****1.add        2.del****\n");
	printf("****3.search  4.modify****\n");
	printf("****5.show      6.sort****\n");
	printf("****7.clear     0.exit****\n");
	printf("**************************\n");
}

Realization of various functions of address book

Initialize address book (empty address book contacts)

  • Note:
  1. After creation, we also need to initialize, otherwise it is a random value
  2. Similarly, clearing the address book is also equivalent to initializing the address book (the implementation code is consistent, and some details can be modified by yourself)
  • Reference code:
//Initialize address book
void InitContact(struct Contact* p)
{
	p->sz = 0;
	//Initializing arrays using memory functions
	memset(p->data, 0, sizeof(p->data));
}

Add contacts

  • Note:
  1. First, judge whether the address book is full before operation
  2. Add information after judgment. Remember to increase the number of people used by + 1 if the addition is successful
  • Reference code:
//Add contacts
void AddContact(struct Contact*p)
{
	if (p->sz == PEOINFO_MAX)
	{
		printf("The address book contact is full and cannot be added!\n");
	}
	else
	{
		printf("Please enter the name of the new contact:");
		scanf("%s", p->data[p->sz].name);
		printf("Please enter the age of the new contact:");
		scanf("%d", &p->data[p->sz].age);
		printf("Please enter the gender of the new contact:");
		scanf("%s", p->data[p->sz].sex);
		printf("Please enter the phone number of the new contact:");
		scanf("%s", p->data[p->sz].number);
		printf("Please enter the address of the new contact:");
		scanf("%s", p->data[p->sz].addr);
		p->sz++;
		printf("Add contacts%s success!\n", p->data[p->sz].name);
	}
	return;
}

Delete address book contact

  • Note:
  1. To delete a contact, first check whether the contact exists in the address book (traversal), and then operate
  2. To delete a contact, we can choose to use the overwrite method to assign the information of the next contact to the previous one
  3. After deletion, remember to - 1 the number of people used
  • Reference code:
//Delete address book contact
void DelContact(struct Contact* p)
{
	char name[NAME_MAX];
	printf("Please enter the contact name to delete:\n");
	scanf("%s", &name);
	for (int i = 0; i < p->sz; i++)
	{
		//strcmp is used for string comparison
		if (strcmp(name, p->data[i].name) == 0)
		{
			for (int j = i; j < p->sz - 1; j++)
			{
				//strcpy is used for string assignment
				strcpy(p->data[j].name , p->data[j + 1].name);
				p->data[j].age = p->data[j + 1].age;
				strcpy(p->data[j].sex , p->data[j + 1].sex);
				strcpy(p->data[j].number , p->data[j + 1].number);
				strcpy(p->data[j].addr , p->data[j + 1].addr);
			}
			p->sz--;
			printf("Delete address book contact%s success!\n", name);
			return;
		}
	}
	printf("Unable to find contacts in the address book%s!\n",name);
	return;
	
}

Find contacts in contacts

  • Note:
  1. Similarly, we need to determine whether the contact we are looking for exists
  2. If yes, we have to display the relevant information of the contact
  • Reference code:
//Find contacts in contacts
void SearchContact(struct Contact* p)
{
	char name[NAME_MAX];
	printf("Please enter the name of the contact you want to operate on:\n");
	scanf("%s", &name);
	for (int i = 0; i < p->sz; i++)
	{
		if (strcmp(name, p->data[i].name) == 0)
		{
			printf("Contact name:%s\n", p->data[i].name);
			printf("Contact's age:%d\n", p->data[i].age);
			printf("Gender of contact:%s\n",p->data[i].sex);
			printf("Contact's phone number:%s\n", p->data[i].number);
			printf("Contact's address:%s\n", p->data[i].addr);
			return;//You can quit after the show
		}
	}
//If the previous conditions are not met, there is no contact
	printf("The contact cannot be found in the address book!\n");
	return;
}

Modify contact information

  • Note:
  1. Similarly, we still need to see whether the contact exists. If it exists, the information will be displayed first
  2. There are two schemes for modification: 1. Re-enter and 2. Select the required information to modify
  3. Here we choose scheme 2 for more humanization, of course, rough scheme 1 is also OK
  4. For the main logic of scheme 2, we can use the do while loop
  5. switch is used to select the implementation
  6. For options, we can write a selection interface
  • Reference code:
//Operation options
void option()
{
	printf("**************************\n");
	printf("****1.name       2.age****\n");
	printf("****3.sex     4.number****\n");
	printf("****5.addr      0.exit****\n");
	printf("**************************\n");
}

//Modify address book contact information
void ModifyContact(struct Contact* p)
{
	int pos=-1;
	int intput = -1;
	ShowContact(p);
	char name[NAME_MAX];
	printf("Please enter the name of the contact you want to operate on:\n");
	scanf("%s", &name);
	for (int i = 0; i < p->sz; i++)
	{
		if (strcmp(name, p->data[i].name) == 0)
		{
			//Find the record location and display it
			printf("Contact name:%s\n", p->data[i].name);
			printf("Contact's age:%d\n", p->data[i].age);
			printf("Gender of contact:%s\n", p->data[i].sex);
			printf("Contact's phone number:%s\n", p->data[i].number);
			printf("Contact's address:%s\n", p->data[i].addr);
			pos = i;
			break;
		}
	}
	//Exit if not found
	if(pos==-1)
	{
		printf("The contact cannot be found in the address book!\n");
		return;
	}
	do 
	{
		option();
		printf("Please enter the option to modify:->\n");
		scanf("%d", &intput);
		switch (intput)
		{
		case 0:
			printf("Exit modification succeeded!\n");
			break;
		case 1:
			printf("Please enter a new name:\n");
			scanf("%s", &p->data[pos].name);
			break;
		case 2:
			printf("Please enter a new age:\n");
			scanf("%d", &p->data[pos].age);
			break;
		case 3:
			printf("Please enter a new gender:\n");
			scanf("%d", &p->data[pos].sex);
			break;
		case 4:
			printf("Please enter a new number:\n");
			scanf("%d", &p->data[pos].number);
			break;
		case 5:
			printf("Please enter a new address:\n");
			scanf("%d", &p->data[pos].addr);
			break;
		default:
			printf("Input error, please re-enter:\n");
		}
	} while (intput);
	return;
}

Show contacts

  • Note:
  1. For the sake of beauty, we can get a form
  2. Just show the contact information and traverse it directly
  • Reference code:
//Show contacts
void ShowContact(struct Contact* p)
{
	//Tabulation
	printf("------------------------\n");
	printf("||%20s|\t%5s|\t%11s|\t%10s|\t%30s||\n",
		"name", "age", "sex", "tele", "addr");
	printf("------------------------\n");
	for (int i = 0; i < p->sz; i++)
	{
		printf("||%20s|\t%5d|\t%11s|\t%10s|\t%30s||\n", 
			p->data[i].name,
			p->data[i].age,
			p->data[i].sex, 
			p->data[i].number,
			p->data[i].addr);
		printf("------------------------\n");
	}
	return;
}

Sort address book contacts

  • Note:
  1. For sorting, we can use the qsort function
  2. For the qsort function, we need to implement the corresponding comparison function
  3. The entity logic of the selected sorting method is the same as that of the selected modification method
  4. For the selection method interface, we can use the selection interface mentioned in the modification method
  • Reference code:
//Implementation of parameter comparison function of qsort function
int cmp_con_name(const void* e1,const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->name, ((struct Peoinfo*)e2)->name);
}

int cmp_con_age(const void* e1, const void* e2)
{
	return ((struct Peoinfo*)e1)->age - ((struct Peoinfo*)e2)->age;
}

int cmp_con_sex(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->sex, ((struct Peoinfo*)e2)->sex);
}

int cmp_con_number(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->number, ((struct Peoinfo*)e2)->number);
}

int cmp_con_addr(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->addr, ((struct Peoinfo*)e2)->addr);
}
//Address book sorting
void SortContact(struct Contact* p)
{
	int intput=-1;
	do
	{
		option();
		printf("Please enter options for sorting method:\n");
		scanf("%d", &intput);
		switch (intput)
		{
		case 0:
			printf("Exit modification succeeded!\n");
			break;
		case 1:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_name);
			ShowContact(p);
			break;
		case 2:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_age);
			ShowContact(p);
			break;
		case 3:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_sex);
			ShowContact(p);
			break;
		case 4:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_number);
			ShowContact(p);
			break;
		case 5:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_addr);
			ShowContact(p);
			break;
		default:
			printf("Input error, please re-enter:\n");
		}
	} while (intput);
	return;
}

Note: if you have any questions about the qsort function, please refer to the blogger's article:

⭐ High order pointer ⭐ Callback function (callback calculator / bubble sort / qsort function)

Overall effect drawing

Attach the source code

  • contact.h:
#define _CRT_SECURE_NO_WARNINGS
#pragma once
//Specific data macro definition methods, including various header files, and declarations of structures and functions
#include<stdio.h>
#include<string.h>

//Maximum number of messages received (preprocessing instructions for easy maintenance)
#define NAME_MAX 20
#define NUMBER_MAX 11
#define SEX_MAX  10
#define ADDR_MAX 30

#define PEOINFO_MAX 100

//Personal information structure
struct Peoinfo 
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	int number[NUMBER_MAX];
	char addr[ADDR_MAX];
};

//Address book structure
struct Contact
{
	//Total contact capacity
	struct Peoinfo data[PEOINFO_MAX];
	//Number of records used
	int sz;
};

//Initialize address book (empty address book)
void InitContact(struct Contact* p);
//Add contacts
void AddContact(struct Contact* p);
//Delete address book contact
void DelContact(struct Contact* p);
//Find contacts in contacts
void SearchContact(struct Contact* p);
//Modify address book contact information
void ModifyContact(struct Contact* p);
//Show contacts
void ShowContact(struct Contact* p);
//Address book sorting
void SortContact(struct Contact* p);

//Operation options
void option();

int cmp_con_name(void* e1, void* e2);

int cmp_con_age(void* e1, const void* e2);

int cmp_con_sex(const void* e1, const void* e2);

int cmp_con_number(const void* e1, const void* e2);

int cmp_con_addr(const void* e1, const void* e2);
  • tast.c:
//The whole process and logic of writing address book
#include "contact.h"

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

//The callback function needs to pass in the function address (calling function) and address book address (operating address book)
void Calo(void(*pc)(struct Peoinfo*i), struct Contact* p)
{
	pc(p);//pc() is a function call, and the parameter passed in p is the address book address
}
//Subject logic
int main()
{
	int intput;
	struct Contact con;
	InitContact(&con);
	//Write a compass array, the element is a function pointer (convenient for calling functions and passing parameters)
	void(*table[8])(struct Contract* pc) = { 0,AddContact,DelContact,SearchContact,ModifyContact,ShowContact,SortContact,InitContact };
	//Basic logic loop
	do 
	{
		menu();
		printf("Please enter what you want to do next:->\n");
		scanf("%d", &intput);
		if (intput > 0 && intput <=7 )
		{
			printf("Successfully entered the selected operation!\n");
			Calo(table[intput],&con);//Callback operation
		}
		else if (intput == 0)
		{
			printf("Exit operation succeeded!!\n");
			break;
		}
		else
		{
			printf("Input error! Please reselect:->\n");
		}
	} while (intput);//Exit if intput is 0
}
  • contact.c:
//Address book function
#include "contact.h"

//Initialize address book
void InitContact(struct Contact* p)
{
	p->sz = 0;
	//Initializing arrays using memory functions
	memset(p->data, 0, sizeof(p->data));
}

//Add contacts
void AddContact(struct Contact*p)
{
	if (p->sz == PEOINFO_MAX)
	{
		printf("The address book contact is full and cannot be added!\n");
	}
	else
	{
		printf("Please enter the name of the new contact:");
		scanf("%s", p->data[p->sz].name);
		printf("Please enter the age of the new contact:");
		scanf("%d", &p->data[p->sz].age);
		printf("Please enter the gender of the new contact:");
		scanf("%s", p->data[p->sz].sex);
		printf("Please enter the phone number of the new contact:");
		scanf("%s", p->data[p->sz].number);
		printf("Please enter the address of the new contact:");
		scanf("%s", p->data[p->sz].addr);
		p->sz++;
		printf("Add contacts%s success!\n", p->data[p->sz].name);
	}
	return;
}

//Delete address book contact
void DelContact(struct Contact* p)
{
	char name[NAME_MAX];
	printf("Please enter the contact name to delete:\n");
	scanf("%s", &name);
	for (int i = 0; i < p->sz; i++)
	{
		//strcmp is used for string comparison
		if (strcmp(name, p->data[i].name) == 0)
		{
			for (int j = i; j < p->sz - 1; j++)
			{
				//strcpy is used for string assignment
				strcpy(p->data[j].name , p->data[j + 1].name);
				p->data[j].age = p->data[j + 1].age;
				strcpy(p->data[j].sex , p->data[j + 1].sex);
				strcpy(p->data[j].number , p->data[j + 1].number);
				strcpy(p->data[j].addr , p->data[j + 1].addr);
			}
			p->sz--;
			printf("Delete address book contact%s success!\n", name);
			return;
		}
	}
	printf("Unable to find contacts in the address book%s!\n",name);
	return;
	
}

//Find contacts in contacts
void SearchContact(struct Contact* p)
{
	char name[NAME_MAX];
	printf("Please enter the name of the contact you want to operate on:\n");
	scanf("%s", &name);
	for (int i = 0; i < p->sz; i++)
	{
		if (strcmp(name, p->data[i].name) == 0)
		{
			printf("Contact name:%s\n", p->data[i].name);
			printf("Contact's age:%d\n", p->data[i].age);
			printf("Gender of contact:%s\n",p->data[i].sex);
			printf("Contact's phone number:%s\n", p->data[i].number);
			printf("Contact's address:%s\n", p->data[i].addr);
			return;
		}
	}
	printf("The contact cannot be found in the address book!\n");
	return;
}

//Operation options
void option()
{
	printf("**************************\n");
	printf("****1.name       2.age****\n");
	printf("****3.sex     4.number****\n");
	printf("****5.addr      0.exit****\n");
	printf("**************************\n");
}

//Modify address book contact information
void ModifyContact(struct Contact* p)
{
	int pos=-1;
	int intput = -1;
	ShowContact(p);
	char name[NAME_MAX];
	printf("Please enter the name of the contact you want to operate on:\n");
	scanf("%s", &name);
	for (int i = 0; i < p->sz; i++)
	{
		if (strcmp(name, p->data[i].name) == 0)
		{
			//Find the record location and display it
			printf("Contact name:%s\n", p->data[i].name);
			printf("Contact's age:%d\n", p->data[i].age);
			printf("Gender of contact:%s\n", p->data[i].sex);
			printf("Contact's phone number:%s\n", p->data[i].number);
			printf("Contact's address:%s\n", p->data[i].addr);
			pos = i;
			break;
		}
	}
	//Exit if not found
	if(pos==-1)
	{
		printf("The contact cannot be found in the address book!\n");
		return;
	}
	do 
	{
		option();
		printf("Please enter the option to modify:->\n");
		scanf("%d", &intput);
		switch (intput)
		{
		case 0:
			printf("Exit modification succeeded!\n");
			break;
		case 1:
			printf("Please enter a new name:\n");
			scanf("%s", &p->data[pos].name);
			break;
		case 2:
			printf("Please enter a new age:\n");
			scanf("%d", &p->data[pos].age);
			break;
		case 3:
			printf("Please enter a new gender:\n");
			scanf("%d", &p->data[pos].sex);
			break;
		case 4:
			printf("Please enter a new number:\n");
			scanf("%d", &p->data[pos].number);
			break;
		case 5:
			printf("Please enter a new address:\n");
			scanf("%d", &p->data[pos].addr);
			break;
		default:
			printf("Input error, please re-enter:\n");
		}
	} while (intput);
	return;
}

//Show contacts
void ShowContact(struct Contact* p)
{
	//Tabulation
	printf("------------------------\n");
	printf("||%20s|\t%5s|\t%11s|\t%10s|\t%30s||\n",
		"name", "age", "sex", "tele", "addr");
	printf("------------------------\n");
	for (int i = 0; i < p->sz; i++)
	{
		printf("||%20s|\t%5d|\t%11s|\t%10s|\t%30s||\n",
			p->data[i].name,
			p->data[i].age,
			p->data[i].sex,
			p->data[i].number,
			p->data[i].addr);
		printf("------------------------\n");
	}
	return;
}

//Implementation of parameter comparison function of qsort function
int cmp_con_name(const void* e1,const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->name, ((struct Peoinfo*)e2)->name);
}

int cmp_con_age(const void* e1, const void* e2)
{
	return ((struct Peoinfo*)e1)->age - ((struct Peoinfo*)e2)->age;
}

int cmp_con_sex(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->sex, ((struct Peoinfo*)e2)->sex);
}

int cmp_con_number(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->number, ((struct Peoinfo*)e2)->number);
}

int cmp_con_addr(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->addr, ((struct Peoinfo*)e2)->addr);
}
//Address book sorting
void SortContact(struct Contact* p)
{
	int intput=-1;
	do
	{
		option();
		printf("Please enter options for sorting method:\n");
		scanf("%d", &intput);
		switch (intput)
		{
		case 0:
			printf("Exit modification succeeded!\n");
			break;
		case 1:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_name);
			ShowContact(p);
			break;
		case 2:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_age);
			ShowContact(p);
			break;
		case 3:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_sex);
			ShowContact(p);
			break;
		case 4:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_number);
			ShowContact(p);
			break;
		case 5:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_addr);
			ShowContact(p);
			break;
		default:
			printf("Input error, please re-enter:\n");
		}
	} while (intput);
	return;
}

Dynamic address book

For the implementation of static address book, we use array to store data

However, the contact capacity stored in such an address book is limited (it may be less or larger)

This problem can be avoided by implementing a dynamic address book (using dynamic memory management)

For the implementation of dynamic address book, in fact, you only need to modify a few places in the static address book

Note: the knowledge of dynamic memory management will be explained in detail later

Address book structure

  • Reference code:
//Address book structure
struct Contact
{
	//Total contact capacity
	int capacity;
	//Mark the first address of the dynamic address book
	struct Peoinfo *data;
	//Number of records used
	int sz;
};

Initialize address book

Use malloc to open up a dynamic space of the default size

  • Reference code:
//Initialize address book
void InitContact(struct Contact* p)
{
	p->capacity = C_SZ;
	p->sz = 0;
	p->data=(struct Peoinfo*)malloc(sizeof(struct Peoinfo) * C_SZ);
	LoadContact(p);
}
//Default capacity size
#define C_SZ  2
//Default add size
#define PLUS  3

Address book capacity increase

  • Note:
  1. Judge when adding contacts in the address book (we encapsulate it into a function here)
  2. When the number of people is equal to the capacity, increase the capacity (use realloc to adjust the size of dynamic development space)
  3. If the capacity increase fails, an error is printed and the program ends
  • Reference code:
//Check that the address book is full
void CheakContact(struct Contact* p)
{
	if (p->sz == p->capacity)
	{
		//If the number of users is full, apply for more space
		struct Peoinfo* ptr = (struct Peoinfo*)realloc(p->data, sizeof(struct Peoinfo) * (C_SZ + PLUS));
		//If ptr is not NULL, the development is successful
		if (ptr != NULL)
		{
			p->data = ptr;
			p->capacity += PLUS;
		}
		else
		{
			perror("CheakContact");//Print out the cause of the error
			exit(1);//End program
		}
	}
}

Address book destruction

  • Note:

When exiting the address book, we need to free the dynamically opened space (use the free function) (otherwise, memory leakage may occur)

  • Reference code:
//Dynamic address book needs to be released after applying for space
void DestoryContact(struct Contact* p)
{
	free(p->data);
	p -> data = NULL;
	p->capacity = 0;
	p->sz = 0;
}

Data saving

After our address book is written, if we still want the address book to save the contact data we entered (open the address book after exiting)

Note: This requires a little knowledge of file operation (which will be explained in detail in the later topics)

output data

Before the end of the address book operation, we let the contact data of the address book be output to the specified file in binary form

(save data in file)

  • Reference code:
//Save address book data
void SaveContact(struct Contact* p)
{
	//fopen function: finds the specified file and returns the address of the file
	//wb: open in write only mode (to output data, open a binary file)
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		//If the opening fails, an error message is printed
		perror("SaveContact");
		return;
	}
	for (int i = 0; i < p->sz; i++)
	{
		//fwrite: binary output
		fwrite(p->data+i, sizeof(struct Peoinfo), 1, pf);
	}
	//Release after pf is used up
	fclose(pf);
	pf = NULL;
	return;
}

Input data (load data)

The next time you enter the address book, input the original saved data into the memory

  • Reference code:
//Load address book data
void LoadContact(struct Contact*p)
{
	//rb: open a binary file as read-only
	FILE* pf = fopen("contact.txt","rb");
	if (pf == NULL)
	{
		perror("Loadcontact");
		return;
	} 
	//Save data temporarily
	struct Peoinfo tmp = { 0 };
	//fread: binary input (return 1 if the input data is complete, otherwise return 0)
	while (fread(&tmp, sizeof(struct Peoinfo), 1, pf))
	{
		//Judge whether capacity increase is required during input
		CheakContact(p);
		p->data[p->sz] = tmp;
		p->sz++;
	}
	//release
	fclose(pf);
	pf = NULL;
	return;
}

Attach the source code

  • contact.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
//Specific data macro definition methods, including various header files, and declarations of structures and functions
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//Maximum number of messages received (preprocessing instructions for easy maintenance)
#define NAME_MAX 20
#define NUMBER_MAX 11
#define SEX_MAX  10
#define ADDR_MAX 30

//Default capacity size
#define C_SZ  2
//Default add size
#define PLUS  3

//Personal information structure
struct Peoinfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	int number[NUMBER_MAX];
	char addr[ADDR_MAX];
};

//Address book structure
struct Contact
{
	//Total contact capacity
	int capacity;
	//Mark the first address of the dynamic address book
	struct Peoinfo *data;
	//Number of records used
	int sz;
};

//Initialize address book (empty address book)
void InitContact(struct Contact* p);
//Add contacts
void AddContact(struct Contact* p);
//Delete address book contact
void DelContact(struct Contact* p);
//Find contacts in contacts
void SearchContact(struct Contact* p);
//Modify address book contact information
void ModifyContact(struct Contact* p);
//Show contacts
void ShowContact(struct Contact* p);
//Address book sorting
void SortContact(struct Contact* p);
//Clear contacts (release)
void DestoryContact(struct Contact* p);
void SaveContact(struct Contact* p);
void LoadContact(struct Contact* p);


//Operation options
void option();

int cmp_con_name(void* e1, void* e2);

int cmp_con_age(void* e1, const void* e2);

int cmp_con_sex(const void* e1, const void* e2);

int cmp_con_number(const void* e1, const void* e2);

int cmp_con_addr(const void* e1, const void* e2);
  • contact.c
//Address book function
#include "contact.h"

//Check that the address book is full
void CheakContact(struct Contact* p)
{
	if (p->sz == p->capacity)
	{
		//If the number of users is full, apply for more space
		struct Peoinfo* ptr = (struct Peoinfo*)realloc(p->data, sizeof(struct Peoinfo) * (C_SZ + PLUS));
		//If ptr is not NULL, the development is successful
		if (ptr != NULL)
		{
			p->data = ptr;
			p->capacity += PLUS;
		}
		else
		{
			perror("LoadContact");
			exit(1);
		}
	}
}

//Load address book data
void LoadContact(struct Contact*p)
{
	//rb: open a binary file as read-only
	FILE* pf = fopen("contact.txt","rb");
	if (pf == NULL)
	{
		perror("Loadcontact");
		return;
	} 
	//Save data temporarily
	struct Peoinfo tmp = { 0 };
	//fread: binary input (return 1 if the input data is complete, otherwise return 0)
	while (fread(&tmp, sizeof(struct Peoinfo), 1, pf))
	{
		//Judge whether capacity increase is required during input
		CheakContact(p);
		p->data[p->sz] = tmp;
		p->sz++;
	}
	//release
	fclose(pf);
	pf = NULL;
	return;
}

//Initialize address book
void InitContact(struct Contact* p)
{
	p->capacity = C_SZ;
	p->sz = 0;
	p->data=(struct Peoinfo*)malloc(sizeof(struct Peoinfo) * C_SZ);
	LoadContact(p);
}

//Add contacts
void AddContact(struct Contact* p)
{
	CheakContact(p);
		printf("Please enter the name of the new contact:");
		scanf("%s", p->data[p->sz].name);
		printf("Please enter the age of the new contact:");
		scanf("%d", &p->data[p->sz].age);
		printf("Please enter the gender of the new contact:");
		scanf("%s", p->data[p->sz].sex);
		printf("Please enter the phone number of the new contact:");
		scanf("%s", p->data[p->sz].number);
		printf("Please enter the address of the new contact:");
		scanf("%s", p->data[p->sz].addr);
		printf("Add contacts%s success!\n", p->data[p->sz].name);
		p->sz++;
	
	return;
}

//Delete address book contact
void DelContact(struct Contact* p)
{
	if (p->sz == 0)
	{
		printf("No contact, unable to delete!\n");
		return;
	}
	char name[NAME_MAX];
	printf("Please enter the contact name to delete:\n");
	scanf("%s", &name);
	for (int i = 0; i < p->sz; i++)
	{
		//strcmp is used for string comparison
		if (strcmp(name, p->data[i].name) == 0)
		{
			for (int j = i; j < p->sz - 1; j++)
			{
				//strcpy is used for string assignment
				strcpy(p->data[j].name, p->data[j + 1].name);
				p->data[j].age = p->data[j + 1].age;
				strcpy(p->data[j].sex, p->data[j + 1].sex);
				strcpy(p->data[j].number, p->data[j + 1].number);
				strcpy(p->data[j].addr, p->data[j + 1].addr);
			}
			p->sz--;
			printf("Delete address book contact%s success!\n", name);
			return;
		}
	}
	printf("Unable to find contacts in the address book%s!\n", name);
	return;

}

//Find contacts in contacts
void SearchContact(struct Contact* p)
{
	char name[NAME_MAX];
	printf("Please enter the name of the contact you want to operate on:\n");
	scanf("%s", &name);
	for (int i = 0; i < p->sz; i++)
	{
		if (strcmp(name, p->data[i].name) == 0)
		{
			printf("Contact name:%s\n", p->data[i].name);
			printf("Contact's age:%d\n", p->data[i].age);
			printf("Gender of contact:%s\n", p->data[i].sex);
			printf("Contact's phone number:%s\n", p->data[i].number);
			printf("Contact's address:%s\n", p->data[i].addr);
			return;
		}
	}
	printf("The contact cannot be found in the address book!\n");
	return;
}

//Operation options
void option()
{
	printf("**************************\n");
	printf("****1.name       2.age****\n");
	printf("****3.sex     4.number****\n");
	printf("****5.addr      0.exit****\n");
	printf("**************************\n");
}

//Modify address book contact information
void ModifyContact(struct Contact* p)
{
	int pos = -1;
	int intput = -1;
	ShowContact(p);
	char name[NAME_MAX];
	printf("Please enter the name of the contact you want to operate on:\n");
	scanf("%s", &name);
	for (int i = 0; i < p->sz; i++)
	{
		if (strcmp(name, p->data[i].name) == 0)
		{
			//Find the record location and display it
			printf("Contact name:%s\n", p->data[i].name);
			printf("Contact's age:%d\n", p->data[i].age);
			printf("Gender of contact:%s\n", p->data[i].sex);
			printf("Contact's phone number:%s\n", p->data[i].number);
			printf("Contact's address:%s\n", p->data[i].addr);
			pos = i;
			break;
		}
	}
	//Exit if not found
	if (pos == -1)
	{
		printf("The contact cannot be found in the address book!\n");
		return;
	}
	do
	{
		option();
		printf("Please enter the option to modify:->\n");
		scanf("%d", &intput);
		switch (intput)
		{
		case 0:
			printf("Exit modification succeeded!\n");
			break;
		case 1:
			printf("Please enter a new name:\n");
			scanf("%s", &p->data[pos].name);
			break;
		case 2:
			printf("Please enter a new age:\n");
			scanf("%d", &p->data[pos].age);
			break;
		case 3:
			printf("Please enter a new gender:\n");
			scanf("%d", &p->data[pos].sex);
			break;
		case 4:
			printf("Please enter a new number:\n");
			scanf("%d", &p->data[pos].number);
			break;
		case 5:
			printf("Please enter a new address:\n");
			scanf("%d", &p->data[pos].addr);
			break;
		default:
			printf("Input error, please re-enter:\n");
		}
	} while (intput);
	return;
}

//Show contacts
void ShowContact(struct Contact* p)
{
	//Tabulation
	printf("------------------------\n");
	printf("||%20s|\t%5s|\t%11s|\t%10s|\t%30s||\n",
		"name", "age", "sex", "tele", "addr");
	printf("------------------------\n");
	for (int i = 0; i < p->sz; i++)
	{
		printf("||%20s|\t%5d|\t%11s|\t%10s|\t%30s||\n",
			p->data[i].name,
			p->data[i].age,
			p->data[i].sex,
			p->data[i].number,
			p->data[i].addr);
		printf("------------------------\n");
	}
	return;
}

//Implementation of parameter comparison function of qsort function
int cmp_con_name(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->name, ((struct Peoinfo*)e2)->name);
}

int cmp_con_age(const void* e1, const void* e2)
{
	return ((struct Peoinfo*)e1)->age - ((struct Peoinfo*)e2)->age;
}

int cmp_con_sex(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->sex, ((struct Peoinfo*)e2)->sex);
}

int cmp_con_number(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->number, ((struct Peoinfo*)e2)->number);
}

int cmp_con_addr(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->addr, ((struct Peoinfo*)e2)->addr);
}
//Address book sorting
void SortContact(struct Contact* p)
{
	int intput = -1;
	do
	{
		option();
		printf("Please enter options for sorting method:\n");
		scanf("%d", &intput);
		switch (intput)
		{
		case 0:
			printf("Exit modification succeeded!\n");
			break;
		case 1:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_name);
			ShowContact(p);
			break;
		case 2:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_age);
			ShowContact(p);
			break;
		case 3:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_sex);
			ShowContact(p);
			break;
		case 4:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_number);
			ShowContact(p);
			break;
		case 5:
			qsort(p->data, p->sz, sizeof(p->data[0]), cmp_con_addr);
			ShowContact(p);
			break;
		default:
			printf("Input error, please re-enter:\n");
		}
	} while (intput);
	return;
}

//Dynamic address book needs to be released after applying for space
void DestoryContact(struct Contact* p)
{
	free(p->data);
	p -> data = NULL;
	p->capacity = 0;
	p->sz = 0;
}

//Save address book data
void SaveContact(struct Contact* p)
{
	//fopen function: finds the specified file and returns the address of the file
	//wb: open in write only mode (to output data, open a binary file)
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		//If the opening fails, an error message is printed
		perror("SaveContact");
		return;
	}
	for (int i = 0; i < p->sz; i++)
	{
		//fwrite: binary output
		fwrite(p->data+i, sizeof(struct Peoinfo), 1, pf);
	}
	//Release after pf is used up
	fclose(pf);
	pf = NULL;
	return;
}
  • test.c
//The whole process and logic of writing address book
#include "contact.h"

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

//The callback function needs to pass in the function address (calling function) and address book address (operating address book)
void Calo(void(*pc)(struct Peoinfo* i), struct Contact* p)
{
	pc(p);//pc() is a function call, and the parameter passed in p is the address book address
}
//Subject logic
int main()
{
	int intput;
	struct Contact con;
	InitContact(&con);
	//Write a compass array, the element is a function pointer (convenient for calling functions and passing parameters)
	void(*table[8])(struct Contract* pc) = { 0,AddContact,DelContact,SearchContact,ModifyContact,ShowContact,SortContact,DestoryContact };
	//Basic logic loop
	do
	{
		menu();
		printf("Please enter what you want to do next:->\n");
		scanf("%d", &intput);
		if (intput > 0 && intput <= 7)
		{
			printf("Successfully entered the selected operation!\n");
			Calo(table[intput], &con);//Callback operation
		}
		else if (intput == 0)
		{
			SaveContact(&con);
			Calo(table[7], &con);
			printf("Exit operation succeeded!!\n");
			break;
		}
		else
		{
			printf("Input error! Please reselect:->\n");
		}
	} while (intput);//Exit if intput is 0
}

Posted by eits on Mon, 27 Sep 2021 16:47:28 -0700