Simulation to realize the address book of dynamic memory version

1. The header file contact.h

Enumerate all options of the address book in the header file. Define a structure type to represent the information of a person in the address book, and use typedef to rename the structure type to PeoInfo type. Define another structure type to represent the address book, and use typedef to rename it to the Contact type. The structure members include PeoInfo *data (data points to the structure type (PeoInfo type) data space used to store personal information in the address book), int sz (record the number of valid personal information in the address book), int capacity (record the current capacity of the address book). Write the declaration of each function. contact.h:

#pragma once

#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>//qsort,malloc,realloc,free,calloc对应的头文件

#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
#define DEFAULT_SZ 3
#define INC_SZ 2

enum Option
{
    
    
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	CLEAR
};

//定义一个结构体类型,表示通讯录中一个人的信息,这里用了typedef重命名
typedef struct PeoInfo
{
    
    
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;

//定义一个结构体类型,表示通讯录,这里用了typedef重命名
typedef struct Contact
{
    
    
	PeoInfo *data;//data指向用来存放通讯录中个人信息的结构体类型(PeoInfo类型)数据的空间
	int sz;//记录通讯录中有效的个人的信息的个数
	int capacity;//记录通讯录当前的容量
}Contact, * pContact;

//初始化通讯录
void InitContact(Contact* pc);

//销毁通讯录
void DestoryContact(Contact* pc);

//增加指定联系人
void AddContact(Contact* pc);

//显示联系人
void ShowContact(const Contact* pc);

//删除指定联系人
//void DelContact(Contact* pc);
void DelContact(pContact pc);

//查找指定联系人
void SearchContact(const Contact* pc);

//修改指定联系人
void ModifyContact(Contact* pc);

//排序联系人
void SortContact(Contact* pc);

//清空联系人
void ClearContact(Contact* pc);

2. The source file test.c used to test the address book function

#define _CRT_SECURE_NO_WARNINGS
#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");
}

int main()
{
    
    
	int input = 0;
	Contact con;//定义一个变量,它的类型是结构体类型,表示通讯录
	//初始化通讯录
	InitContact(&con);
	do
	{
    
    
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT:
			SortContact(&con);
			break;
		case CLEAR:
			ClearContact(&con);
			break;
		case EXIT:
			DestoryContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

3. The source file contact.c that implements the address book function

3.1 Initialize address book

Use the malloc function to apply to the memory for storing 3 (DEFAULT_SZ) structure type (PeoInfo type) data size space, in bytes. It is best to judge the return value of malloc, because if the memory development fails, malloc will return a null pointer. Assign sz in the address book as 0, and assign capacity as 3 (DEFAULT_SZ). Initialize address book:

//初始化通讯录
void InitContact(Contact* pc)
{
    
    
	assert(pc);
	pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));
	if (pc->data == NULL)//malloc的返回值最好判断一下,因为如果内存开辟失败,malloc会返回空指针
	{
    
    
		printf("通讯录初始化失败:%s\n", strerror(errno));
		return;
	}
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
}

3.2 Destroy address book

Because the malloc function is used to apply for space in the memory, the free function is used to release the memory space when exiting the address book. Exiting the address book means destroying the address book, and assigning sz and capacity to 0 in the address book. Destroy address book:

//销毁通讯录
void DestoryContact(Contact* pc)
{
    
    
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
	printf("释放内存\n");
}

3.3 The expansion function used to support the function of adding contacts

Static is added in front of this function. When the number of effective personal information in the address book is equal to the capacity of the address book, use realloc to expand the capacity of the address book to increase the capacity of the address book by 2 (INC_SZ). It is best to judge the return value of realloc, because if the memory development fails, realloc will return a null pointer. Then assign the initial address of the opened space to the pointer variable ptr, then assign the value of the pointer variable ptr to the pointer variable data, and add 2 to the capacity of the address book (INC_SZ). If the capacity expansion fails, return 0; if the capacity expansion is successful, or if the capacity is not enough and does not need to be expanded, return 1. Expansion function:

//用来支持增加联系人功能,函数前加了static
//扩容失败,返回0
//扩容成功,或者容量还够不需要扩容,返回1
static int CheckCapacity(Contact* pc)
{
    
    
	if (pc->sz == pc->capacity)
	{
    
    
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
    
    
			printf("CheckCapacity:%s\n", strerror(errno));
			return 0;
		}
		else
		{
    
    
			pc->data = ptr;
			pc->capacity += INC_SZ;
			printf("扩容成功,通讯录当前容量为:%d\n", pc->capacity);
			return 1;//扩容成功返回1
		}
	}
	return 1;//容量还够不需要扩容,返回1
}

3.4 Add Designated Contact

Call the expansion function, if the expansion function returns 0 and the expansion fails, then the function of adding the specified contact will stop, and do not go any further; if the expansion is successful, then input various information of the contact to be added to increase the contact, and then the number of valid personal information in the address book++.

//增加指定联系人
void AddContact(Contact* pc)
{
    
    
	assert(pc);
	if (0 == CheckCapacity(pc))//已经调用完了扩容函数
	{
    
    
		printf("空间不够,扩容失败\n");
		return;
	}
	printf("请输入姓名:>");
	scanf("%s", pc->data[pc->sz].name);//[]的优先级大于.,.的优先级大于->
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));//pc->data[pc->sz].age要取地址,因为age是int类型
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz++;
	printf("添加联系人成功\n");
}

3.5 Display contacts

After we add, delete, modify, sort, and clear the address book, we need to print out the address book for observation. At this time, we need a function to display contacts. First print the title, and then use the for loop to print sz contacts, and the subscript of data starts from 0. Show contacts:

//显示联系人
void ShowContact(const Contact* pc)
{
    
    
	assert(pc);
	int i = 0;
	//打印标题
	printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++)//有sz个人,打印sz次
	{
    
    
		printf("%-10s %-4d %-5s %-12s %-30s\n",
			pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}

3.6 The search name function used to support the functions of deleting, searching and modifying contacts

This function is not declared in the header file. We hope that this function is written to support functions such as deletion, search, and modification. The function is not exposed (I don’t want to be seen by others), so add static before the function, and add static functions in front. This function can only be used inside the .c file where it is located. Other source files cannot find it, and other source files cannot use it.
Using the for loop is equivalent to traversing the data array to find the name of the person. The data pointer is actually used, and the strcmp function is used to compare the input name and the traversed name of the person. If the name of the person to be searched is found, the subscript (equivalent to the pointer offset) of the structure type (PeoInfo type) array where the name of the searched person is located is returned; -1 is returned if the name of the searched person is not found. Find the name function:

//这个函数没有在头文件中声明,我们希望这个函数写出来是为了支持删除、查找、修改这样的功能的,函数没有暴露出来(不愿意给别人看到),所以在函数前加上static
//前面加上static的函数,这个函数只能在自己所在的.c文件内部使用,其它的源文件发现不了它,其它的源文件用不上它,在名字上也不会跟它冲突
static int FindByName(const Contact* pc, char name[])
{
    
    
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->sz; i++)//相当于遍历data数组查找人名,实际用的是data指针
		if (0 == strcmp(pc->data[i].name, name))
		{
    
    
			return i;//返回要查找的人名所在的结构体类型数组的下标
		}
	return -1;
}

3.7 Delete designated contacts

Define an array of char type, because the name of the person to be deleted will be entered later. If the number sz of valid personal information in the address book is 0, the address book is empty and cannot be deleted. If sz is not 0, input the name of the person to be deleted, call the search name function, if the name of the person to be deleted cannot be found, the person to be deleted does not exist; if the name of the person to be deleted is found, use the for loop to delete the elements of the structure type (PeoInfo type) array with pos as the subscript (equivalent to the pointer offset), and assign all elements behind the element with pos as the subscript to the front (shift one bit). Then sz- -, after sz- -, the szth person will not be printed out, and the printed one will show sz-1 person. Delete a specified contact:

//删除指定联系人
void DelContact(pContact pc)
{
    
    
	assert(pc);
	char name[MAX_NAME] = {
    
     0 };//因为后面要输入要删除人的名字
	if (pc->sz == 0)
	{
    
    
		printf("通讯录为空,无法删除\n");
		return;
	}
	//1、查找要删除的联系人,即查找要删除的人人名所在的结构体类型(PeoInfo类型)数组的下标
	printf("输入要删除人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (-1 == pos)
	{
    
    
		printf("要删除的人不存在\n");
		return;
	}
	//2、删除,删除pos为下标的结构体类型(PeoInfo类型)数组的元素
	int i = 0;
	for (i = pos; i < pc->sz - 1; i++)
	{
    
    
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除联系人成功\n");
}

3.8 Find the specified contact person

Define an array of char type, because the name of the person to be searched will be entered later. Input the name of the person to be searched, call the search name function, if the name of the person to be searched cannot be found, the person to be searched does not exist; if the name of the person to be searched is found, then print the elements of the structure type (PeoInfo type) array with pos as the subscript (equivalent to the pointer offset), and print out various information of the contact. Find a specific contact:

//查找指定联系人
void SearchContact(const Contact* pc)
{
    
    
	assert(pc);
	char name[MAX_NAME] = {
    
     0 };//因为后面要输入要查找人的名字
	printf("请输入要查找的人的名字:>");
	scanf("%s", name);
	//查找联系人
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
    
    
		printf("要查找的人不存在\n");
		return;
	}
	//打印要查找的联系人
	printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("%-10s %-4d %-5s %-12s %-30s\n",
		pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);
}

3.9 Modify the designated contact person

Define an array of char type, because the name of the person to be modified will be entered later. Enter the name of the person to be modified, call the search name function, if the name of the person to be modified cannot be found, the person to be modified does not exist; if the name of the person to be modified is found, then re-enter the contents of each member of the array of structure type (PeoInfo type) with pos as the subscript (equivalent to the pointer offset). Modify the specified contact:

//修改指定联系人
void ModifyContact(Contact* pc)
{
    
    
	assert(pc);
	char name[MAX_NAME] = {
    
     0 };//因为后面要输入要修改人的名字
	printf("输入要修改人的名字:>");
	scanf("%s", name);
	//查找要修改的联系人 
	int pos = FindByName(pc, name);
	if (-1 == pos)
	{
    
    
		printf("要修改的人不存在\n");
		return;
	}
	//修改
	printf("请输入姓名:>");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pos].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pos].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pos].addr);
	printf("修改联系人成功\n");
}

3.10 Sort Contacts

Here is to sort by name, call the qsort function to sort.

//排序联系人,按名字来排序
int cmp_by_name(const void* e1, const void* e2)
{
    
    
	assert(e1 && e2);
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
    
    
	assert(pc);
	qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
	printf("排序联系人成功\n");
}

3.11 Clear contacts

To clear the contacts means to destroy the address book first, and then initialize the address book

//清空联系人
void ClearContact(Contact* pc)
{
    
    
	assert(pc);
	DestoryContact(pc);
	InitContact(pc);
	printf("清空联系人成功\n");
}

Guess you like

Origin blog.csdn.net/zhanlongsiqu/article/details/129772823