前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手把手教你用C语言实现通讯录管理系统

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

作者头像
平凡之路.
发布2024-10-09 15:05:08
910
发布2024-10-09 15:05:08
举报
文章被收录于专栏:学习

一、引言

在日常生活中,我们经常需要管理大量的联系人信息,如姓名、性别、年龄、电话和地址等。为了方便地管理和查询这些信息,我们可以使用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("%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. 展示所有联系人

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

代码语言:javascript
复制
//展示通讯录
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. 保存文件

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

代码语言: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("%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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、引言
  • 二、需求分析
    • 1.项目概述
      • 2.功能需求
        • 3.数据结构设计
        • 三、功能设计
          • 1.初始化通讯录
            • 2. 添加联系人
              • 3. 删除联系人
                • 4. 修改联系人
                  • 5. 查询联系人
                    • 6. 展示所有联系人
                      • 7. 保存文件
                        • 8. 加载数据
                        • 四、完整代码
                          • 1.Contact.h
                            • 2.Contact.c
                              • 3.main.c
                              • 五、测试运行
                              • 六、总结
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档