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

2024-10-09 15:05:08 浏览数 (3)

一、引言

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

二、需求分析

1.项目概述

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

2.功能需求

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

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

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

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

3.数据结构设计

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

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

三、功能设计

1.初始化通讯录

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

代码语言:javascript复制
//初始化
void ContactInit(Con* p)
{
	p->arr = NULL;
	p->size = p->capacity = 0;
}

2. 添加联系人

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

代码语言:javascript复制
//检查容量
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. 删除联系人

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

代码语言:javascript复制
//查找数据
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. 修改联系人

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

代码语言:javascript复制
//查找数据
/*
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. 查询联系人

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

代码语言:javascript复制
//查找数据
/*
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("%st%st%st%stt%stn", "姓名", "性别", "年龄", "电话", "地址");
	printf("%st%st%dt%st%stn",
		p->arr[find].name,
		p->arr[find].gender,
		p->arr[find].age,
		p->arr[find].tel,
		p->arr[find].address
	);
}

6. 展示所有联系人

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

代码语言:javascript复制
//展示通讯录
void ContactShow(Con* p)
{
	//表头:姓名  性别  年龄  电话  地址    
	printf("%st%st%st%stt%stn", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < p->size; i  )
	{
		printf("%st%st%dt%st%stn",
			p->arr[i].name,
			p->arr[i].gender,
			p->arr[i].age,
			p->arr[i].tel,
			p->arr[i].address
		);
	}
}

7. 保存文件

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

代码语言:javascript复制
//将数据保存到文件中
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. 加载数据

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

代码语言:javascript复制
//从文件读取历史数据
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

代码语言:javascript复制
#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

代码语言:javascript复制
#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("%st%st%st%stt%stn", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < p->size; i  )
	{
		printf("%st%st%dt%st%stn",
			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("%st%st%st%stt%stn", "姓名", "性别", "年龄", "电话", "地址");
	printf("%st%st%dt%st%stn",
		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

代码语言:javascript复制
#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语言编程的基本技巧,为以后的项目开发奠定基础。当然,这个通讯录管理系统还有许多可以优化的地方,比如增加联系人信息的排序、分页显示等功能,感兴趣的读者可以继续完善。

0 人点赞