catalogue
Specific implementation ideas and processes
Create contact information and address book structure
Realization of various functions of address book
Initialize address book (empty address book contacts)
Address book capacity increase
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:
- Add contact information
- Delete specified contact information
- Find specified contact information
- Modify the specified contact information
- Show all contact information
- Empty all contacts
- 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:
- contact.h: macro definition modifies specific data (convenient for maintenance), including various header files, and declarations of structures and functions
- test.c: the overall process and logic of writing address book
- 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:
- After creation, we also need to initialize, otherwise it is a random value
- 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:
- First, judge whether the address book is full before operation
- 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:
- To delete a contact, first check whether the contact exists in the address book (traversal), and then operate
- To delete a contact, we can choose to use the overwrite method to assign the information of the next contact to the previous one
- 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:
- Similarly, we need to determine whether the contact we are looking for exists
- 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:
- Similarly, we still need to see whether the contact exists. If it exists, the information will be displayed first
- There are two schemes for modification: 1. Re-enter and 2. Select the required information to modify
- Here we choose scheme 2 for more humanization, of course, rough scheme 1 is also OK
- For the main logic of scheme 2, we can use the do while loop
- switch is used to select the implementation
- 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:
- For the sake of beauty, we can get a form
- 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:
- For sorting, we can use the qsort function
- For the qsort function, we need to implement the corresponding comparison function
- The entity logic of the selected sorting method is the same as that of the selected modification method
- 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:
- Judge when adding contacts in the address book (we encapsulate it into a function here)
- When the number of people is equal to the capacity, increase the capacity (use realloc to adjust the size of dynamic development space)
- 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 }