通讯录的实现(C语言版)

本文详细介绍了如何创建一个可存储1000人信息的通讯录,包括添加、删除、查找、修改和显示功能,并实现了动态扩容和文件持久化。通过结构体和函数设计,展示了高效管理个人信息的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现一个通讯录;

通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址

提供方法:

  1. 添加联系人信息
  2. 删除指定联系人信息
  3. 查找指定联系人信息
  4. 修改指定联系人信息
  5. 显示所有联系人信息
  6. 清空所有联系人
  7. 以名字排序所有联系人

目录

通讯录的创建

通讯录功能的实现

添加联系人信息

删除指定联系人信息

查找指定联系人信息

修改指定联系人信息

显示所有联系人信息

清空所有联系人

以名字排序所有联系人

以文件的形式保存(进阶)

实现效果

源码展示


通讯录的创建

首先我们知道通讯录中的信息不可能是单一的类型,他一定是多种数据类型整合而成的,因此需要创建一个结构体来存放通讯录信息:(为了能够方便更改某些信息, 可以把某些量设置为宏)

#define NAME_MAX 15//名字最大长度
#define SEX_MAX 8//性别最大长度
#define TELE_MAX 12//电话号码最大长度
#define ADDS_MAX 30//地址最大长度
struct Telephone
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tele[TELE_MAX];
	char adds[ADDS_MAX];
};

这样一个结构体就可以存放一个人的信息,而要存放1000个人的信息,可以再创建一个结构体用来存放这些结构体数据:

struct TeleInfo
{
	struct Telephone* data;
	int sz;//表示通讯录的容量
};

我们知道这样一个结构体类型占用的内存比较大,而假如我们仅需要存储10个人20个人的信息,这时创建一个容量1000的通讯录就造成了内存的大量浪费,因此我们可以将其改进,设置成动态增长的模式:

#define CAPACITY 3//通讯录初始容量
#define ADD_CAPACITY 2//每次扩容增加的容量大小
#define NAME_MAX 15//名字最大长度
#define SEX_MAX 8//性别最大长度
#define TELE_MAX 12//电话号码最大长度
#define ADDS_MAX 30//地址最大长度
struct Telephone
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tele[TELE_MAX];
	char adds[ADDS_MAX];
};
struct TeleInfo
{
	struct Telephone* data;
	int sz;
	int capacity;
};

初始设置的结构体大小比较小,等到内存不够时再重新开辟空间,这样就可以避免空间的浪费。

而这时再将其初始化,就创建出一个空通讯录:

void Init_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	p->data = (struct Telephone*)malloc(CAPACITY * sizeof(struct Telephone));
	if (p->data == NULL)
	{
		perror("Init_TeleInfo()");
		return;
	}
	p->sz = 0;
	p->capacity = CAPACITY;
}

接着就可以根据要求设计内需了。

通讯录功能的实现

为了能够是的各部分功能都能实现,首先需要两个重要的函数:

1、保证容量功能(如果不够先进行增容)

这个判断函数不通过使用者直接调用,因此可以在函数前添加static:

static int check_TeleInfo(struct TeleInfo* p)
{
	if (p->sz == p->capacity)
	{
		//扩容
		struct Telephone* ptr = (struct Telephone*)realloc(p->data,
			(p->capacity + ADD_CAPACITY) * sizeof(struct Telephone));
		if (ptr == NULL)
		{
			perror("add_TeleInfo()");
			return -1;
		}
		p->data = ptr;
		p->capacity += ADD_CAPACITY;
		return 1;
	}
	return 0;
}

这时通讯录的容量确保是充足的,因此可以进行录入信息。

2、搜索信息功能

对于删除、查找、修改等操作,都需要首先判断通讯录中是否存在该联系人才能进行后续相关操作。因此首先需要写一个查找函数(这个函数同上,不通过使用者直接调用,因此可以在函数前添加static):

static int seek_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	char name[NAME_MAX] = { 0 };
	printf("请输入联系人姓名:>");
	scanf("%s", name);
	int i = 0;
	for (i = 0; i < p->sz; i++)
	{
		if (strcmp(p->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

有了这两个前置函数,就可以无障碍实现各部分功能,具体如下:

添加联系人信息

void add_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	int flag = check_TeleInfo(p);
	if (flag == 1)
		printf("增容成功\n");
	else if (flag == -1)
		return;
	printf("请输入名字:>");
	scanf("%s", p->data[p->sz].name);
	printf("请输入性别:>");
	scanf("%s", p->data[p->sz].sex);
	printf("请输入年龄:>");
	scanf("%d", &(p->data[p->sz].age));
	printf("请输入电话:>");
	scanf("%s", p->data[p->sz].tele);
	printf("请输入地址:>");
	scanf("%s", p->data[p->sz].adds);
	p->sz++;
	printf("添加成功\n");
}

删除指定联系人信息

void del_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	//判断联系人是否存在
	int ret = seek_TeleInfo(p);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
		return;
	}
	else
	{
        //该位置后面的所有信息前移一格
		for (; ret < p->sz; ret++)
			p->data[ret] = p->data[ret + 1];
		p->sz--;
		printf("删除成功\n");
	}
}

查找指定联系人信息

void find_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	int ret = seek_TeleInfo(p);
	if (ret == -1)
		return;
	else
	{
        //这里主要保证上下内容位置统一
		printf("%-10s\t%-10s\t%-10s\t%-10s\t%-20s\n", "姓名", "性别", "年龄", "电话", "地址");
		printf("%-10s\t%-10s\t%-10d\t%-10s\t%-20s\n", p->data[ret].name, p->data[ret].sex,
		p->data[ret].age, p->data[ret].tele, p->data[ret].adds);
	}
}

修改指定联系人信息

void modify_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	//判断联系人是否存在
	int ret = seek_TeleInfo(p);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
		return;
	}
	printf("请输入名字:>");
	scanf("%s", p->data[ret].name);
	printf("请输入性别:>");
	scanf("%s", p->data[ret].sex);
	printf("请输入年龄:>");
	scanf("%d", &(p->data[ret].age));
	printf("请输入电话:>");
	scanf("%s", p->data[ret].tele);
	printf("请输入地址:>");
	scanf("%s", p->data[ret].adds);
}

显示所有联系人信息

void show_TeleInfo(struct TeleInfo* p)
{
	int i = 0;
	printf("%-10s\t%-10s\t%-10s\t%-10s\t%-20s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (i = 0; i < p->sz; i++)
	{
		printf("%-10s\t%-10s\t%-10d\t%-10s\t%-20s\n", p->data[i].name, p->data[i].sex,
			p->data[i].age, p->data[i].tele, p->data[i].adds);
	}
}

清空所有联系人

void destroy_TeleInfo(struct TeleInfo* p)
{
	free(p->data);
	p->data = NULL;
	p->sz = 0;
	p->capacity = 0;
}

以名字排序所有联系人

int cmp_name(const struct Telephone* str1, const struct Telephone* str2)
{
	return strcmp(str1->name, str2->name);
}
void sort_TeleInfo(struct TeleInfo* p)
{
	qsort(p->data, p->sz, sizeof(struct Telephone), cmp_name);
}

以文件的形式保存(进阶)

这时通讯录的功能已经全部实现,不过我们发现这样的通讯录无法保存,即下次使用时并不能找到上次退出前存储的信息。要解决这个问题,其实将信息以文件的形式保存即可。

既然如此,我们就需要在打开时首先读取文件,而在结束退出后保存文件,那么只需添加两个函数,就可以达到保存信息的功能。

读取文件可以在初始化通讯录后进行:

void Init_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	p->data = (struct Telephone*)malloc(CAPACITY * sizeof(struct Telephone));
	if (p->data == NULL)
	{
		perror("Init_TeleInfo()");
		return;
	}
	p->sz = 0;
	p->capacity = CAPACITY;
	load_TeleInfo(p);//仅多一次函数调用
}

读取文件内容函数:

void load_TeleInfo(struct TeleInfo* p)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("load_TeleInfo:fopen()");
		return;
	}
	//读取文件内容并存储在结构体中
	struct Telephone tmp = { 0 };
	while (fread(&tmp, sizeof(struct Telephone), 1, pf))
	{
		check_TeleInfo(p);
		p->data[p->sz] = tmp;
		p->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

通讯录保存可以在退出前进行:

void save_TeleInfo(struct TeleInfo* p)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("save_TeleInfo:fopen");
		return;
	}
	//写文件
	int i = 0;
	while (i < p->sz) 
	{
		fwrite(p->data + i, sizeof(struct Telephone), 1, pf);
		i++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

实现效果

源码展示

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>

#define CAPACITY 3//通讯录容量
#define ADD_CAPACITY 2//每次扩容增加的容量大小
#define NAME_MAX 15//名字最大长度
#define SEX_MAX 8//性别最大长度
#define TELE_MAX 12//电话号码最大长度
#define ADDS_MAX 30//地址最大长度
struct Telephone
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tele[TELE_MAX];
	char adds[ADDS_MAX];
};
struct TeleInfo
{
	struct Telephone* data;
	int sz;
	int capacity;
};
//初始化通讯录
void Init_TeleInfo(struct TeleInfo* p);
//保存通讯录
void save_TeleInfo(struct TeleInfo* pc);
//销毁通讯录
void destroy_TeleInfo(struct TeleInfo* p);
//添加联系人
void add_TeleInfo(struct TeleInfo* p);
//删除指定联系人
void del_TeleInfo(struct TeleInfo* p);
//查找指定联系人
void find_TeleInfo(struct TeleInfo* p);
//修改指定联系人
void modify_TeleInfo(struct TeleInfo* p);
//展示通讯录所有联系人
void show_TeleInfo(struct TeleInfo* p);
//将通讯录按名字排序
void sort_TeleInfo(struct TeleInfo* p);
#include"contact2.h"

static int check_TeleInfo(struct TeleInfo* p)
{
	if (p->sz == p->capacity)
	{
		//扩容
		struct Telephone* ptr = (struct Telephone*)realloc(p->data,
			(p->capacity + ADD_CAPACITY) * sizeof(struct Telephone));
		if (ptr == NULL)
		{
			perror("add_TeleInfo()");
			return -1;
		}
		p->data = ptr;
		p->capacity += ADD_CAPACITY;
		return 1;
	}
	return 0;
}

void load_TeleInfo(struct TeleInfo* p)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("load_TeleInfo:fopen()");
		return;
	}
	//读取文件
	struct Telephone tmp = { 0 };
	while (fread(&tmp, sizeof(struct Telephone), 1, pf))
	{
		check_TeleInfo(p);
		p->data[p->sz] = tmp;
		p->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

void Init_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	p->data = (struct Telephone*)malloc(CAPACITY * sizeof(struct Telephone));
	if (p->data == NULL)
	{
		perror("Init_TeleInfo()");
		return;
	}
	p->sz = 0;
	p->capacity = CAPACITY;
	load_TeleInfo(p);
}
void add_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	int flag = check_TeleInfo(p);
	if (flag == 1)
		printf("增容成功\n");
	else if (flag == -1)
		return;
	printf("请输入名字:>");
	scanf("%s", p->data[p->sz].name);
	printf("请输入性别:>");
	scanf("%s", p->data[p->sz].sex);
	printf("请输入年龄:>");
	scanf("%d", &(p->data[p->sz].age));
	printf("请输入电话:>");
	scanf("%s", p->data[p->sz].tele);
	printf("请输入地址:>");
	scanf("%s", p->data[p->sz].adds);
	p->sz++;
	printf("添加成功\n");
}

static int seek_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	char name[NAME_MAX] = { 0 };
	printf("请输入联系人姓名:>");
	scanf("%s", name);
	int i = 0;
	for (i = 0; i < p->sz; i++)
	{
		if (strcmp(p->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}
void find_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	int ret = seek_TeleInfo(p);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
		return;
	}
	else
	{
		printf("%-10s\t%-10s\t%-10s\t%-10s\t%-20s\n", "姓名", "性别", "年龄", "电话", "地址");
		printf("%-10s\t%-10s\t%-10d\t%-10s\t%-20s\n", p->data[ret].name, p->data[ret].sex,
		p->data[ret].age, p->data[ret].tele, p->data[ret].adds);
	}
}
void del_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	//判断联系人是否存在
	int ret = seek_TeleInfo(p);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
		return;
	}
	else
	{
		for (; ret < p->sz; ret++)
			p->data[ret] = p->data[ret + 1];
		p->sz--;
		printf("删除成功\n");
	}
}

void modify_TeleInfo(struct TeleInfo* p)
{
	assert(p);
	//判断联系人是否存在
	int ret = seek_TeleInfo(p);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
		return;
	}
	printf("请输入名字:>");
	scanf("%s", p->data[ret].name);
	printf("请输入性别:>");
	scanf("%s", p->data[ret].sex);
	printf("请输入年龄:>");
	scanf("%d", &(p->data[ret].age));
	printf("请输入电话:>");
	scanf("%s", p->data[ret].tele);
	printf("请输入地址:>");
	scanf("%s", p->data[ret].adds);

}

void show_TeleInfo(struct TeleInfo* p)
{
	int i = 0;
	printf("%-10s\t%-10s\t%-10s\t%-10s\t%-20s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (i = 0; i < p->sz; i++)
	{
		printf("%-10s\t%-10s\t%-10d\t%-10s\t%-20s\n", p->data[i].name, p->data[i].sex,
			p->data[i].age, p->data[i].tele, p->data[i].adds);
	}
}

int cmp_name(const struct Telephone* str1, const struct Telephone* str2)
{
	return strcmp(str1->name, str2->name);
}
void sort_TeleInfo(struct TeleInfo* p)
{
	qsort(p->data, p->sz, sizeof(struct Telephone), cmp_name);
}

void save_TeleInfo(struct TeleInfo* p)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("save_TeleInfo:fopen");
		return;
	}
	//写文件
	int i = 0;
	while (i < p->sz) 
	{
		fwrite(p->data + i, sizeof(struct Telephone), 1, pf);
		i++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

void destroy_TeleInfo(struct TeleInfo* p)
{
	free(p->data);
	p->data = NULL;
	p->sz = 0;
	p->capacity = 0;
}
#include"contact2.h"

void menu()
{
	printf("***********************\n");
	printf("****1.add   2.delete***\n");
	printf("****3.seek  4.modify***\n");
	printf("****5.show  6.clear ***\n");
	printf("****7.sort  0.exit  ***\n");
	printf("***********************\n");
}
enum choose
{
	EXIT,
	ADD,
	DELETE,
	SEEK,
	MODIFY,
	SHOW,
	CLEAR,
	SORT
};
int main()
{
	int input;
	struct TeleInfo con;
	//初始化通讯录
	Init_TeleInfo(&con);
	do
	{
		menu();
		printf("请选择你要进行的操作:>");
		scanf("%d", &input);
		switch (input)
		{
		case EXIT:
			save_TeleInfo(&con);
			printf("保存成功\n");
			destroy_TeleInfo(&con);
			printf("退出成功\n");
			break;
		case ADD:
			add_TeleInfo(&con);
			break;
		case DELETE:
			del_TeleInfo(&con);
			break;
		case SEEK:
			find_TeleInfo(&con);
			break;
		case MODIFY:
			modify_TeleInfo(&con);
			break;
		case SHOW:
			show_TeleInfo(&con);
			break;
		case CLEAR:
			destroy_TeleInfo(&con);
			break;
		case SORT:
			sort_TeleInfo(&con);
			break;		
		default:
			break;
		}
	} while (input);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值