联系无间:构建你的数字通讯录

目录

一、引言

二、需求分析

1. 项目概述

2. 功能需求

3. 数据结构设计

三、功能设计

1. 初始化通讯录

2. 添加联系人

3. 删除联系人

4. 修改联系人

5. 查询联系人

6. 展示所有联系人

7. 保存数据到文件

8. 加载数据

四、完整代码

1.Contact.h

 2.Contact.c

3.main.c

五、测试运行

六、总结


一、引言

在现代生活中,联系人信息管理已经成为人们日常生活中不可或缺的一部分。无论是工作还是社交,能够高效地管理联系人信息如姓名、性别、年龄、电话和地址等,都是一项重要的技能。为了解决这一需求,本文将带领大家一步步实现一个简单的通讯录管理系统,使用C语言编写,以便于存储、管理和查询联系人信息。

二、需求分析

1. 项目概述

本通讯录管理系统旨在提供一个友好的用户界面,允许用户对联系人信息进行增删改查等操作。同时,为了确保数据的持久化,系统还将支持将数据保存到文件中,以便在下次启动程序时能够恢复之前的联系人信息。

2. 功能需求

系统的基本功能需求包括:

  • 添加联系人:允许用户输入并保存新的联系人信息。

  • 删除联系人:根据姓名删除已存在的联系人信息。

  • 修改联系人:对已存在的联系人进行信息修改。

  • 查询联系人:根据姓名查询特定联系人的详细信息。

  • 展示联系人:以列表形式展示所有已保存的联系人信息。

  • 加载数据:程序启动时从指定文件加载历史联系人数据。

  • 保存数据:在程序关闭前将当前联系人数据持久化到文件中。

3. 数据结构设计

为了有效存储联系人信息,我们定义了一个名为personInfo的结构体,包含以下字段:

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");
}

接下来,通过ContactAdd函数实现添加联系人的具体逻辑。

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 ContactDestroy(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 ContactDestroy(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);//保存数据到文件
	ContactDestroy(&con);//销毁
	return 0;
}

五、测试运行

菜单界面

添加联系人

展示联系人 

六、总结

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

评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

平凡程序猿~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值