手把手教你用C语言实现通讯录管理系统

目录

一、引言

二、需求分析

1.项目概述

2.功能需求 

3.数据结构设计

三、功能设计 

1.初始化通讯录

2. 添加联系人

3. 删除联系人

4. 修改联系人

5. 查询联系人

6. 展示所有联系人

7. 保存文件

8. 加载数据

 四、完整代码 

1.Contact.h

 2.Contact.c

3.main.c

五、测试运行

六、总结


一、引言

在日常生活中,我们经常需要管理大量的联系人信息,如姓名、性别、年龄、电话和地址等。为了方便地管理和查询这些信息,我们可以使用C语言编写一个通讯录管理系统。本文将带领大家一步步实现这个系统。

二、需求分析

1.项目概述

通讯录管理系统是一款用于存储、管理和操作联系人信息的程序。该系统允许用户添加、删除、修改、查找和展示联系人,并将数据持久化到文件中,以便在程序重新启动时可以恢复数据。

2.功能需求 

添加联系人:允许用户添加新的联系人信息
删除联系人:根据用户输入的联系人姓名,删除对应的联系人信息。

修改联系人:允许用户修改已添加的联系人信息。
查询联系人:根据用户输入的联系人姓名,查询对应的联系人信息。

显示联系人:显示所有已添加的联系人信息。
加载数据:在程序启动时,系统需要从指定的文件中读取联系人数据,并恢复通讯录的状态。

保存数据: 在程序关闭前,系统需要将当前通讯录数据持久化到文件中,以便在下次启动程序时可以恢复数据。

3.数据结构设计

为了存储联系人信息,我们定义一个结构体如下:

typedef struct personInfo
{
	char name[NAME_MAX];//姓名
	char gender[GENDER_MAX];//性别
	int age;//年龄
	char tel[TEL_MAX];//电话号码
	char address[ADDRESS_MAX];//地址
}Per;

三、功能设计 

1.初始化通讯录

初始化通讯录管理系统,准备接收用户操作。

//初始化
void ContactInit(Con* p)
{
	p->arr = NULL;
	p->size = p->capacity = 0;
}

2. 添加联系人

提示用户输入联系人的姓名、性别、年龄、电话和地址。
提示用户添加成功。

//检查容量
void checkcapacity(Con* p)
{
	if (p->size == p->capacity)
	{
		int newcapacity = p->capacity == 0 ? 4 : 2 * p->capacity;
		DataType* tmp = (DataType*)realloc(p->arr, newcapacity * sizeof(DataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(1);
		}
		//空间申请成功
		p->arr = tmp;
		p->capacity = newcapacity;
	}
}
//顺序表尾插
void SLPushBack(Con* p, DataType x)
{
	assert(p);
	checkcapacity(p);
	p->arr[p->size++] = x;
}
//添加数据
void ContactAdd(Con* p)
{
	Per info;
	printf("请输入要添加的联系人姓名:\n");
	scanf("%s", info.name);
	printf("请输入要添加的联系人性别:\n");
	scanf("%s", info.gender);
	printf("请输入要添加的联系人年龄:\n");
	scanf("%d", &info.age);
	printf("请输入要添加的联系人电话:\n");
	scanf("%s", info.tel);
	printf("请输入要添加的联系人地址:\n");
	scanf("%s", info.address);
	SLPushBack(p, info);
	printf("添加成功!\n");
}

3. 删除联系人

提示用户输入要删除联系人的姓名。
在通讯录文件中查找对应的联系人。
如果找到,删除该联系人的信息,并提示用户删除成功。
如果未找到,提示用户联系人不存在。

//查找数据
int FindByName(Con* p, char name[])
{
	for (int i = 0; i < p->size; i++)
	{
		if (strcmp(p->arr[i].name, name) == 0)
			return i;//找到了
	}
	return -1;//没有找到
}
//删除数据
void ContactDel(Con* p)
{
	//前提是数据必须存在才能删除---查找数据是否存在
	char name[NAME_MAX];
	printf("请输入要删除的联系人姓名:\n");
	scanf("%s", name);
	int find = FindByName(p, name);
	if (find < 0)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}
	SLErase(p, find);
	printf("删除成功!\n");
}

4. 修改联系人

提示用户输入要修改联系人的姓名。
在通讯录文件中查找对应的联系人。
如果找到,允许用户修改联系人的信息,并提示用户修改成功。
如果未找到,提示用户联系人不存在。

//查找数据
/*
int FindByName(Con* p, char name[])
{
	for (int i = 0; i < p->size; i++)
	{
		if (strcmp(p->arr[i].name, name) == 0)
			return i;//找到了
	}
	return -1;//没有找到
}
*/
//通讯录的修改
void ContactMod(Con* p)
{
	//前提是数据必须存在才能修改---查找数据是否存在
	char name[NAME_MAX];
	printf("请输入要修改的联系人姓名:\n");
	scanf("%s", name);
	int find = FindByName(p, name);
	if (find < 0)
	{
		printf("要修改的联系人不存在!\n");
		return;
	}
	//直接修改
	printf("请输入修改后的姓名:\n");
	scanf("%s", p->arr[find].name);
	printf("请输入修改后的性别:\n");
	scanf("%s", p->arr[find].gender);
	printf("请输入修改后的年龄:\n");
	scanf("%d", &p->arr[find].age);
	printf("请输入修改后的电话:\n");
	scanf("%s", p->arr[find].tel);
	printf("请输入修改后的地址:\n");
	scanf("%s", p->arr[find].address);
	printf("修改成功!\n");
}

5. 查询联系人

提示用户输入要查询联系人的姓名。
在通讯录中查找对应的联系人。
如果找到,显示该联系人的详细信息。
如果未找到,提示用户联系人不存在。

//查找数据
/*
int FindByName(Con* p, char name[])
{
	for (int i = 0; i < p->size; i++)
	{
		if (strcmp(p->arr[i].name, name) == 0)
			return i;//找到了
	}
	return -1;//没有找到
}
*/
void ContactFind(Con* p)
{
	char name[NAME_MAX];
	printf("请输入要查找的联系人姓名:\n");
	scanf("%s", name);
	int find = FindByName(p, name);
	if (find < 0)
	{
		printf("要查找的联系人不存在!\n");
		return;
	}
	printf("%s\t%s\t%s\t%s\t\t%s\t\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%s\t%s\t%d\t%s\t%s\t\n",
		p->arr[find].name,
		p->arr[find].gender,
		p->arr[find].age,
		p->arr[find].tel,
		p->arr[find].address
	);
}

6. 展示所有联系人

读取通讯录中的所有联系人信息。
在屏幕上以表格形式展示所有联系人信息。

//展示通讯录
void ContactShow(Con* p)
{
	//表头:姓名  性别  年龄  电话  地址    
	printf("%s\t%s\t%s\t%s\t\t%s\t\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < p->size; i++)
	{
		printf("%s\t%s\t%d\t%s\t%s\t\n",
			p->arr[i].name,
			p->arr[i].gender,
			p->arr[i].age,
			p->arr[i].tel,
			p->arr[i].address
		);
	}
}

7. 保存文件

在程序退出前,保存所有更改到通讯录文件。

//将数据保存到文件中
void SaveContact(Con* p) {
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL) {
		perror("fopen error!\n");
		return;
	}
	//将通讯录数据写入文件
	for (int i = 0; i < p->size; i++)
	{
		fwrite(p->arr + i, sizeof(Per), 1, pf);
	}
	printf("通讯录数据保存成功!\n");
}

8. 加载数据

程序启动时,自动加载通讯录文件中的历史数据。
如果文件不存在或为空,则初始化一个空的通讯录。

//从文件读取历史数据
void LoadContact(Con* p) {
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL) {
		perror("fopen error!\n");
		return;
	}
	//循环读取文件数据
	Per info;
	printf("正在导入历史数据...\n");
	Sleep(1000);
	while (fread(&info, sizeof(Per), 1, pf))
	{
		SLPushBack(p, info);
	}
	printf("历史数据导入通讯录成功!\n");
	system("pause");
	system("cls");
}

 四、完整代码 

1.Contact.h

#pragma once
#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDRESS_MAX 100
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<windows.h>
//定义结构体存储个人信息(自定义类型)
typedef struct personInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char address[ADDRESS_MAX];
}Per;
typedef Per DataType;//这里类型为自定义类型Per
//通讯录:底层为顺序表
typedef struct Contact
{
	DataType* arr;
	int size;//有效数据个数
	int capacity;//容量
}Con;

//初始化通讯录
void ContactInit(Con* p);
//销毁通讯录
void ContactDestory(Con* p);
//展示通讯录
void ContactShow(Con* p);
//添加数据
void ContactAdd(Con* p);
//删除数据
void ContactDel(Con* p);
//通讯录的修改
void ContactMod(Con* p);
//通讯录的查找
void ContactFind(Con* p);
//从文件读取历史数据
void LoadContact(Con* p);
//将数据保存到文件中
void SaveContact(Con* p);

 2.Contact.c

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
//初始化
void ContactInit(Con* p)
{
	p->arr = NULL;
	p->size = p->capacity = 0;
}
//销毁
void ContactDestory(Con* p)
{
	if (p->arr)
	{
		free(p->arr);
	}
	p->arr = NULL;
	p->size = p->capacity = 0;
}
//检查容量
void checkcapacity(Con* p)
{
	if (p->size == p->capacity)
	{
		int newcapacity = p->capacity == 0 ? 4 : 2 * p->capacity;
		DataType* tmp = (DataType*)realloc(p->arr, newcapacity * sizeof(DataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(1);
		}
		//空间申请成功
		p->arr = tmp;
		p->capacity = newcapacity;
	}
}
//顺序表尾插
void SLPushBack(Con* p, DataType x)
{
	assert(p);
	checkcapacity(p);
	p->arr[p->size++] = x;
}
//删除指定位置的数据
void SLErase(Con* p, int pos)
{
	assert(p);
	assert(pos >= 0 && pos < p->size);
	for (int i = pos; i <= p->size - 2; i++)
	{
		p->arr[i] = p->arr[i + 1];
	}
	p->size--;
}
//添加数据
void ContactAdd(Con* p)
{
	Per info;
	printf("请输入要添加的联系人姓名:\n");
	scanf("%s", info.name);
	printf("请输入要添加的联系人性别:\n");
	scanf("%s", info.gender);
	printf("请输入要添加的联系人年龄:\n");
	scanf("%d", &info.age);
	printf("请输入要添加的联系人电话:\n");
	scanf("%s", info.tel);
	printf("请输入要添加的联系人地址:\n");
	scanf("%s", info.address);
	SLPushBack(p, info);
	printf("添加成功!\n");
}
//查找数据
int FindByName(Con* p, char name[])
{
	for (int i = 0; i < p->size; i++)
	{
		if (strcmp(p->arr[i].name, name) == 0)
			return i;//找到了
	}
	return -1;//没有找到
}
//删除数据
void ContactDel(Con* p)
{
	//前提是数据必须存在才能删除---查找数据是否存在
	char name[NAME_MAX];
	printf("请输入要删除的联系人姓名:\n");
	scanf("%s", name);
	int find = FindByName(p, name);
	if (find < 0)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}
	SLErase(p, find);
	printf("删除成功!\n");
}
//展示通讯录
void ContactShow(Con* p)
{
	//表头:姓名  性别  年龄  电话  地址    
	printf("%s\t%s\t%s\t%s\t\t%s\t\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < p->size; i++)
	{
		printf("%s\t%s\t%d\t%s\t%s\t\n",
			p->arr[i].name,
			p->arr[i].gender,
			p->arr[i].age,
			p->arr[i].tel,
			p->arr[i].address
		);
	}
}
//通讯录的修改
void ContactMod(Con* p)
{
	//前提是数据必须存在才能修改---查找数据是否存在
	char name[NAME_MAX];
	printf("请输入要修改的联系人姓名:\n");
	scanf("%s", name);
	int find = FindByName(p, name);
	if (find < 0)
	{
		printf("要修改的联系人不存在!\n");
		return;
	}
	//直接修改
	printf("请输入修改后的姓名:\n");
	scanf("%s", p->arr[find].name);
	printf("请输入修改后的性别:\n");
	scanf("%s", p->arr[find].gender);
	printf("请输入修改后的年龄:\n");
	scanf("%d", &p->arr[find].age);
	printf("请输入修改后的电话:\n");
	scanf("%s", p->arr[find].tel);
	printf("请输入修改后的地址:\n");
	scanf("%s", p->arr[find].address);
	printf("修改成功!\n");
}
//通讯录的查找
void ContactFind(Con* p)
{
	char name[NAME_MAX];
	printf("请输入要查找的联系人姓名:\n");
	scanf("%s", name);
	int find = FindByName(p, name);
	if (find < 0)
	{
		printf("要查找的联系人不存在!\n");
		return;
	}
	printf("%s\t%s\t%s\t%s\t\t%s\t\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%s\t%s\t%d\t%s\t%s\t\n",
		p->arr[find].name,
		p->arr[find].gender,
		p->arr[find].age,
		p->arr[find].tel,
		p->arr[find].address
	);
}
//从文件读取历史数据
void LoadContact(Con* p) {
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL) {
		perror("fopen error!\n");
		return;
	}
	//循环读取文件数据
	Per info;
	printf("正在导入历史数据...\n");
	Sleep(1000);
	while (fread(&info, sizeof(Per), 1, pf))
	{
		SLPushBack(p, info);
	}
	printf("历史数据导入通讯录成功!\n");
	system("pause");
	system("cls");
}
//将数据保存到文件中
void SaveContact(Con* p) {
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL) {
		perror("fopen error!\n");
		return;
	}
	//将通讯录数据写入文件
	for (int i = 0; i < p->size; i++)
	{
		fwrite(p->arr + i, sizeof(Per), 1, pf);
	}
	printf("通讯录数据保存成功!\n");
}

3.main.c

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
void menu()
{
	printf("***************通讯录***************\n");
	printf("****1.添加联系人    2.删除联系人****\n");
	printf("****3.修改联系人    4.查找联系人****\n");
	printf("****5.展示联系人    0.退出并保存****\n");
	printf("************************************\n");

}
int main()
{
	Con con;//创建
	ContactInit(&con);//初始化
	LoadContact(&con);//导入历史数据
	int option = -1;
	int(*pfunc[6])(Con * p) = { 0,ContactAdd,ContactDel,ContactMod,ContactFind,ContactShow }; //转移表
	do
	{
		menu();
		printf("请选择你的操作:\n");
		scanf("%d", &option);
		//转移表开始
		if (option >= 1 && option <= 6)//根据对应的option执行不同操作
		{
			(*pfunc[option])(&con);
		}
		else if (option == 0)
		{
			printf("退出通讯录!\n");
		}
		else
		{
			printf("输入有误,请重新选择!\n");
		}
		system("pause");
		system("cls");//转移表末尾
		//我用的是转移表写,也可以正常使用switch-case语句,使用switch语句就把转移表那段注释掉
		/*switch (option)
		{
		case 1:
			ContactAdd(&con);
			system("pause");
			system("cls");
			break;
		case 2:
			ContactDel(&con);
			system("pause");
			system("cls");
			break;
		case 3:
			ContactMod(&con);
			system("pause");
			system("cls");
			break;
		case 4:
			ContactFind(&con);
			system("pause");
			system("cls");
			break;
		case 5:
			ContactShow(&con);
			system("pause");
			system("cls");
			break;
		case 0:
			printf("退出通讯录!\n");
			break;
		default:
			printf("输入有误,请重新选择!\n");
			system("pause");
			system("cls");
			break;
		}*/

	} while (option != 0);
	SaveContact(&con);//保存数据到文件
	ContactDestory(&con);//销毁
	return 0;
}

五、测试运行

菜单界面

添加联系人

展示联系人 

六、总结

本文通过一个简单的通讯录管理系统,介绍了C语言在文件操作、结构体、函数等方面的应用。通过学习本文,读者可以掌握C语言编程的基本技巧,为以后的项目开发奠定基础。当然,这个通讯录管理系统还有许多可以优化的地方,比如增加联系人信息的排序、分页显示等功能,感兴趣的读者可以继续完善。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值