C语言: 可存储数据的动态内存通讯录

🎉🎉大家好,我是青衫,这期我们来模拟实现一个能够存储数据的动态内存通讯录🎉🎉

✨✨通讯录功能:

1、添加联系人

2、删除联系人

3、查找联系人

4、修改联系人

5、保存已经存储的联系人(存储进文件,以便下次运行时读取)

6、展示通讯录

7、退出通讯录

✨✨所要用到的函数:

1、打印菜单-------void menu()

2、初始化通讯录-------void inint_contact(Contact* pc)

3、添加联系人-------void add_contact(Contact* pc)

4、删除联系人-------void add_contact(Contact* pc)

5、查找联系人-------void find_contact(Contact* pc)

6、修改联系人-------void modify_contact(Contact* pc)

7、展示联系人-------void show_contact(Contact* pc)

8、检查通讯录是否已满-------void check_contact(Contact* pc)

9、文件存储通讯录数据-------void save_contact(Contact* pc)

10、加载文件中的数据-------void load_contact(Contact* pc)

11、销毁通讯录-------void destroy_contact(Contact* pc)

12、通过名字查找-------static int find_per_by_name(Contact* pc,char name[ ])

文件准备

一个名为“contact.h”的头文件,一个名为“contact.c”的源文件,一个“test.c”的源文件。两个源文件分别包含头文件。

源文件准备工作

包含头文件以及宏定义和结构体定义:

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define DEFAULT_SZ 3
#define INC 2

#define MAX_NAME 10
#define MAX_TELE 12
#define MAX_ADDRESS 100
#define MAX_SEX 5

//人
typedef struct Person
{
	char name[MAX_NAME];
	char tele[MAX_TELE];
	char address[MAX_ADDRESS];
	char sex[MAX_SEX];
	int age;
}Person;

typedef struct Contact
{
	//人物数据
	Person* data;
	//存储的数量
	int size;
	//总容量
	int capacity;
}Contact;

函数声明:

//添加
void add_contact(Contact* pc);

//删除
void delete_contact(Contact* pc);

//查找
void find_contact(Contact* pc);

//修改
void modify_contact(Contact* pc);

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

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

//检查通讯录是否满了
void check_contact(Contact* pc);

//展示通讯录
void show_contact(Contact* pc);

//文件保存通讯录
void save_contact(Contact* pc);

//加载文件中的通讯录联系人信息
void load_contact(Contact* pc);

接下来我们该实现函数了

🛸1.1打印菜单

void menu()
{
	printf("************************************\n");
	printf("*****  1、添加     2、删除 *********\n");
	printf("*******3、查找     4、修改 *********\n");
	printf("***********5、展示联系人************\n");
	printf("***********  0、退出  **************\n");
	printf("************************************\n");
}

🛸1.2初始化通讯录

void inint_contact(Contact* pc)
{
	assert(pc);
	pc->size = 0;
	pc->capacity = 2;
	pc->data = (Person*)malloc(DEFAULT_SZ * sizeof(Person));
	if (pc->data == NULL)
	{
		perror("InitContact::malloc");
		return;
	}
	//加载文件中存储好的通讯录联系人信息
	load_contact(pc);
}

这里用malloc开辟足够的空间来存储联系人。

load_Contact函数是读取文件中的数据的函数,后文会讲到如何实现。

1.3 检查通讯录是否已满

void check_contact(Contact* pc)
{
	if (pc->size == pc->capacity)
	{
		Person* ptr = realloc(pc->data, (pc->capacity + INC) * sizeof(Person));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += INC;
			printf("增容成功\n");
		}
		else
		{
			perror("add_contact realloc");
			return;
		}
	}
}

这里判断容量capacity是否足够,如果不足了,就用realloc来扩容。扩容后capacity也应该加上扩容的容量。

🛸1.4添加联系人

void add_contact(Contact* pc)
{
	assert(pc);
	check_contact(pc);
	printf("请输入姓名-> ");
	scanf("%s", &pc->data[pc->size].name);
	printf("请输入电话-> ");
	scanf("%s", &pc->data[pc->size].tele);
	printf("请输入地址-> ");
	scanf("%s", &pc->data[pc->size].address);
	printf("请输入性别-> ");
	scanf("%s", &pc->data[pc->size].sex);
	printf("请输入年龄-> ");
	scanf("%d", &pc->data[pc->size].age);
	pc->size++;
	printf("添加成功\n");
}

先断言判断传入的指针非空。

之后逐个输入即可。

🛸1.5通过输入的名字查找到联系人

static int find_per_by_name(Contact* pc,char name[])
{
	assert(pc);
	int i = 0;
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

通过输入的姓名,遍历查找整个通讯录,如果发现相同名字的,那么就返回其对应的下标。

如果找不到,返回-1;

注:这里因为只是在这个文件中实现其他函数的时候用到这个函数,所以用static来声明保护它,让它不能在其他文件中使用。

🛸1.6删除联系人

void delete_contact(Contact* pc)
{
    assert(pc);
    if (pc->size == 0)
    {
        printf("通讯录为空\n");
    }
    else
    {
        char name[MAX_NAME] = { 0 };
        printf("请输入要删除的人的姓名\n");
        scanf("%s", name);
        int pos = find_per_by_name(pc, name);
        if (pos == -1)
        {
            printf("不存在此人\n");
        }
        else
        {
            int j = 0;
            for (j = pos; j < pc->size - 1; j++)
            {
                pc->data[j] = pc->data[j + 1];
            }
            pc->size--;
            printf("删除成功\n");
        }
    }
}

输入要删除的联系人的姓名,然后通过前面实现的 find_per_by_name 函数来查找的所要删除的联系人的下标,然后从后往前覆盖数据,再将通讯录的大小-1即可。

🛸1.7查找联系人

void find_contact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的人名->");
	scanf("%s", name);
	int pos = find_per_by_name(pc, name);
	if (pos == -1)
	{
		printf("不存在此人\n");
	}
	else
	{
		printf("姓名:%s\n", pc->data[pos].name);
		printf("性别:%s\n", pc->data[pos].sex);
		printf("年龄:%d\n", pc->data[pos].age);
		printf("电话:%s\n", pc->data[pos].tele);
		printf("地址:%s\n", pc->data[pos].address);
		printf("\n");
	}
}

还是通过find_per_by_name 函数来查找联系人,然后打印他的信息。

🛸1.8修改联系人

void modify_contact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的人名->");
	scanf("%s", name);
	int pos = find_per_by_name(pc, name);
	if (pos == -1)
	{
		printf("不存在此人\n");
	}
	else
	{
		printf("请输入姓名-> ");
		scanf("%s", &pc->data[pc->size].name);
		printf("请输入电话-> ");
		scanf("%s", &pc->data[pc->size].tele);
		printf("请输入地址-> ");
		scanf("%s", &pc->data[pc->size].address);
		printf("请输入性别-> ");
		scanf("%s", &pc->data[pc->size].sex);
		printf("请输入年龄-> ");
		scanf("%d", &pc->data[pc->size].age);
		printf("修改成功!\n");
	}
}

通过find_per_by_name 函数来查找联系人,然后重新输入新的联系人信息。

🛸1.9展示通讯录的联系人

void show_contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	if (pc->size == 0)
	{
		printf("通讯录为空\n");
		return 1;
	}
	for (; i < pc->size; i++)
	{
		printf("%d\n", i+1);
		printf("姓名:%s\n", pc->data[i].name);
		printf("性别:%s\n", pc->data[i].sex);
		printf("年龄:%d\n", pc->data[i].age);
		printf("电话:%s\n", pc->data[i].tele);
		printf("地址:%s\n", pc->data[i].address);
		printf("\n");
	}
}

将整个通讯录的联系人信息一 一打印一遍。

🛸2.0销毁通讯录

void destroy_contact(Contact* pc)
{
	assert(pc);
	free(pc->data);
	pc->data = NULL;
	pc->size = 0;
	pc->capacity = 0;

free释放之前mallocrealloc申请的内存空间,将指针置空,将容量和大小等归零。

🛸2.1将通讯录中的联系人存储进文件中

void save_contact(Contact* pc)
{
	FILE* pfwritting = fopen("Contact.dat", "wb");
	if (pfwritting == NULL)
	{
		perror("open file for writting");
		return 1;
	}
	//写数据进文件
	for (int i = 0; i < pc->size; i++)
	{
		fwrite(pc->data + i, sizeof(Person), 1, pfwritting);
	}
	fclose(pfwritting);
	pfwritting = NULL;
}

fopen打开文件“Contact.dat”,方式为二进制写入。用一个类型为FILE的指针接收。

用fwrite以二进制的形式写入pc->date+i所指向的数据到文件中。

最后fclose关闭文件,将指针置空。

🛸2.2读取文件中存储的联系人数据

void load_contact(Contact* pc)
{
	Person p1 = { 0 };
	FILE* pfreading = fopen("Contact.dat", "rb");
	if (pfreading == NULL)
	{
		perror("open file for reading");
		return;
	}
	while (fread(&p1, sizeof(Person), 1, pfreading))
	{
		check_contact(pc);
		pc->data[pc->size] = p1;
		pc->size++;
	}
}

fopen打开文件,以二进制形式读取。创建Person类型的临时变量p1。

freadpfreading指向的文件中的内容读取到临时变量p1中。

再用pc->date+i 来接收p1中的内容,存储进通讯录中。

每接收一个,size++;

感谢各位的观看!代码放在最后!

 Contact.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define DEFAULT_SZ 3
#define INC 2

#define MAX_NAME 10
#define MAX_TELE 12
#define MAX_ADDRESS 100
#define MAX_SEX 5

//人
typedef struct Person
{
	char name[MAX_NAME];
	char tele[MAX_TELE];
	char address[MAX_ADDRESS];
	char sex[MAX_SEX];
	int age;
}Person;

typedef struct Contact
{
	//人物数据
	Person* data;
	//存储的数量
	int size;
	//总容量
	int capacity;
}Contact;

//添加
void add_contact(Contact* pc);

//删除
void delete_contact(Contact* pc);

//查找
void find_contact(Contact* pc);

//修改
void modify_contact(Contact* pc);

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

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

//检查通讯录是否满了
void check_contact(Contact* pc);

//展示通讯录
void show_contact(Contact* pc);

//文件保存通讯录
void save_contact(Contact* pc);

//加载文件中的通讯录联系人信息
void load_contact(Contact* pc);

Contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"

void load_contact(Contact* pc)
{
	Person p1 = { 0 };
	FILE* pfreading = fopen("Contact.dat", "rb");
	if (pfreading == NULL)
	{
		perror("open file for reading");
		return;
	}
	while (fread(&p1, sizeof(Person), 1, pfreading))
	{
		check_contact(pc);
		pc->data[pc->size] = p1;
		pc->size++;
	}
}
void inint_contact(Contact* pc)
{
	assert(pc);
	pc->size = 0;
	pc->capacity = 2;
	pc->data = (Person*)malloc(DEFAULT_SZ * sizeof(Person));
	if (pc->data == NULL)
	{
		perror("InitContact::malloc");
		return;
	}
	//加载文件中存储好的通讯录联系人信息
	load_contact(pc);
}

void check_contact(Contact* pc)
{
	if (pc->size == pc->capacity)
	{
		Person* ptr = realloc(pc->data, (pc->capacity + INC) * sizeof(Person));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += INC;
			printf("增容成功\n");
		}
		else
		{
			perror("add_contact realloc");
			return;
		}
	}
}

void add_contact(Contact* pc)
{
	assert(pc);
	check_contact(pc);
	printf("请输入姓名-> ");
	scanf("%s", &pc->data[pc->size].name);
	printf("请输入电话-> ");
	scanf("%s", &pc->data[pc->size].tele);
	printf("请输入地址-> ");
	scanf("%s", &pc->data[pc->size].address);
	printf("请输入性别-> ");
	scanf("%s", &pc->data[pc->size].sex);
	printf("请输入年龄-> ");
	scanf("%d", &pc->data[pc->size].age);
	pc->size++;
	printf("添加成功\n");
}

static int find_per_by_name(Contact* pc,char name[])
{
	assert(pc);
	int i = 0;
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void delete_contact(Contact* pc)
{
	assert(pc);
	if (pc->size == 0)
	{
		printf("通讯录为空\n");
	}
	else
	{
		char name[MAX_NAME] = { 0 };
		printf("请输入要删除的人的姓名\n");
		scanf("%s", name);
		int pos = find_per_by_name(pc, name);
		if (pos == -1)
		{
			printf("不存在此人\n");
		}
		else
		{
			int j = 0;
			for (j = pos; j < pc->size - 1; j++)
			{
				pc->data[j] = pc->data[j + 1];
			}
			pc->size--;
			printf("删除成功\n");
		}
	}
}

void show_contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	if (pc->size == 0)
	{
		printf("通讯录为空\n");
		return 1;
	}
	for (; i < pc->size; i++)
	{
		printf("%d\n", i+1);
		printf("姓名:%s\n", pc->data[i].name);
		printf("性别:%s\n", pc->data[i].sex);
		printf("年龄:%d\n", pc->data[i].age);
		printf("电话:%s\n", pc->data[i].tele);
		printf("地址:%s\n", pc->data[i].address);
		printf("\n");
	}
}

void find_contact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的人名->");
	scanf("%s", name);
	int pos = find_per_by_name(pc, name);
	if (pos == -1)
	{
		printf("不存在此人\n");
	}
	else
	{
		printf("姓名:%s\n", pc->data[pos].name);
		printf("性别:%s\n", pc->data[pos].sex);
		printf("年龄:%d\n", pc->data[pos].age);
		printf("电话:%s\n", pc->data[pos].tele);
		printf("地址:%s\n", pc->data[pos].address);
		printf("\n");
	}
}

void modify_contact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的人名->");
	scanf("%s", name);
	int pos = find_per_by_name(pc, name);
	if (pos == -1)
	{
		printf("不存在此人\n");
	}
	else
	{
		printf("请输入姓名-> ");
		scanf("%s", &pc->data[pc->size].name);
		printf("请输入电话-> ");
		scanf("%s", &pc->data[pc->size].tele);
		printf("请输入地址-> ");
		scanf("%s", &pc->data[pc->size].address);
		printf("请输入性别-> ");
		scanf("%s", &pc->data[pc->size].sex);
		printf("请输入年龄-> ");
		scanf("%d", &pc->data[pc->size].age);
		printf("修改成功!\n");
	}
}

void destroy_contact(Contact* pc)
{
	assert(pc);
	free(pc->data);
	pc->data = NULL;
	pc->size = 0;
	pc->capacity = 0;
}

void save_contact(Contact* pc)
{
	FILE* pfwritting = fopen("Contact.dat", "wb");
	if (pfwritting == NULL)
	{
		perror("open file for writting");
		return 1;
	}
	//写数据进文件
	for (int i = 0; i < pc->size; i++)
	{
		fwrite(pc->data + i, sizeof(Person), 1, pfwritting);
	}
	fclose(pfwritting);
	pfwritting = NULL;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void menu()
{
	printf("************************************\n");
	printf("*****  1、添加     2、删除 *********\n");
	printf("*******3、查找     4、修改 *********\n");
	printf("***********5、展示联系人************\n");
	printf("***********  0、退出  **************\n");
	printf("************************************\n");
}
int main()
{
	Contact con = { 0 };
	inint_contact(&con);
	int input = 0;
	printf("欢迎使用通讯录系统,请选择您要使用的功能: \n");
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			add_contact(&con);
			break;
		case 2:
			delete_contact(&con);
			break;
		case 3:
			find_contact(&con);
		case 4:
			modify_contact(&con);
			break;
		case 5:
			show_contact(&con);
			break;
		case 0:
			save_contact(&con);
			destroy_contact(&con);
			printf("欢迎下次使用\n");
			break;
		default:
			printf("输入有误,请重试\n");
			break;
		}
	} while (input);
	return 0;
}

  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青衫哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值