[项目]-通讯录的实现

news2024/9/22 4:02:01

前言

在这里插入图片描述

各位师傅大家好,我是qmx_07,今天来结合前面所学知识点,写一个能够增删改查,持久化数据的通讯录功能

准备工作

项目 一般会写成多个文件来实现,调用,接口声明,接口实现,这是一种良好的编写习惯

  • test.c //调用
  • contact.h //通讯录的接口声明
  • contact.c//通讯录的接口实现

test.c

#include"contact.h"
void menu()
{
	printf("*****************************************\n");
	printf("*****   1.添加         2.显示      ******\n");
	printf("*****   3.查找         4.修改      ******\n");
	printf("*****   5.删除         6.排序      ******\n");
	printf("*****   7.清空         0.退出      ******\n");
	printf("*****************************************\n");
}
int main()
{
	int input = 0;
	Contact con;
	InitContact(&con);
	do
	{
		menu();
		printf("请输入你要操作的选项:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			ShowContact(&con);
			break;
		case 3:
			SearchContact(&con);
			break;
		case 4:
			ModifContact(&con);
			break;
		case 5:
			DelContact(&con);
			break;
		case 6:
			SortContact(&con);
			break;
		case 7:
			EmptyContact(&con);
			break;
		case 0:
			SaveContact(&con);
			DestroyContact(&con);//销毁
			printf("退出通讯录系统\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

  • 使用do while循环和switch语句,来接收想要选择的功能
  • test.c的作用:打印菜单,接收用户的功能选择

contact.h

typedef struct PeoInfo 
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
}PeoInfo;

typedef struct Contact
{
	PeoInfo* data;//联系人的相关信息
	int sz;//通讯录人数
	int capicity;//通讯录容量
}Contact;

  • 通过结构体PeoInfo 存放联系人的数据,Contact记录通讯录的数据信息
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12

  • 通过宏定义 记录值,比较容易记忆

完整代码:

#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define Init_contact 10 //初始通讯录的容量

#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
}PeoInfo;

typedef struct Contact
{
	PeoInfo* data;
	int sz;//记录通讯录有多少人的
	int capicity;//当前通讯录最大容量
}Contact;

void InitContact(Contact* ps);//初始化通讯录

void AddContact(Contact* ps);//增加联系人的信息

void ShowContact(Contact* ps);//显示所有联系人

void SearchContact(Contact* ps);//查找联系人

void ModifContact(Contact* ps);//修改联系人的信息

void DelContact(Contact* ps);//删除联系人的信息

void SortContact(Contact* ps);//排序

void EmptyContact(Contact* ps);//清空

void SaveContact(Contact* ps);//保存文件

void ReadContact(Contact* ps);//读取文件

void DestroyContact(Contact* ps);//销毁

  • contact.h 主要是 声明通讯录的接口

contact.c

初始化通讯录

void InitContact(Contact* ps)
{
	ps->data = (int*)malloc(sizeof(PeoInfo) * Init_contact);
	if (ps->data == NULL)
	{
		perror("malloc:");
		return;
	}
	ps->sz = 0;
	ps->capicity = Init_contact;
	ReadContact(ps);//如果之前就已经有数据,加载

}

  • 为通讯录初始化数据,开辟容量

判断是否需要扩容

void CheakConTact(Contact* ps)
{
	if (ps->sz == ps->capicity)
	{
		int* ptr = (int*)realloc(ps->data, sizeof(PeoInfo) * (ps->capicity + Init_contact));
		if (ptr == NULL)
		{
			perror("realloc:");
			return;
		}
		else
		{
			ps->data = ptr;
		}
		printf("增容成功!\n");
		ps->capicity += Init_contact;
	}
}

  • 通过realloc函数,对已经开辟的内存,进一步扩容

添加内容

void AddContact(Contact* ps)//增加联系人的信息
{
	assert(ps);
	CheakConTact(ps);//先检查是否需要增容
	printf("请输入联系人的姓名:");
	scanf("%s", ps->data[ps->sz].name);
	printf("请输入联系人的年龄:");
	scanf("%d", &(ps->data[ps->sz].age));
	printf("请输入联系人的性别:");
	scanf("%s", ps->data[ps->sz].sex);
	printf("请输入联系人的电话:");
	scanf("%s", ps->data[ps->sz].tele);
	ps->sz++;
	printf("添加成功!\n");
}

  • 添加通讯录内容,记得要增加通讯录的数量

显示通讯录

  • 通讯录中有数据,那么我们就要打印出来
void ShowContact(Contact* ps)//显示所有联系人
{
	if (ps->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	int i = 0;
	printf("%-5s\t%-4s\t%-4s\t%-15s\n", "姓名", "年龄", "性别", "电话");//水平制表符,左对齐
	for (i = 0; i < ps->sz; i++)
	{
		printf("%-5s\t%-4d\t%-4s\t%-15s\n", ps->data[i].name, ps->data[i].age, ps->data[i].sex, ps->data[i].tele);
	}
}

判断 通讯录成员是否存在

int PanDuan(Contact* ps)//判断有没有此联系人
{
	if (ps->sz == 0)
	{
		printf("通讯录为空!\n");
		return 0;
	}
	char name[MAX_NAME];
	printf("请输入你要查找的联系人的姓名:");
	scanf("%s", name);
	int i = 0;
	for (i = 0; i < ps->sz; i++)
	{
		if (strcmp(ps->data[i].name, name) == 0)
		{
			break;
		}
	}
	return i;
	}

  • 遍历通讯录,做strcmp匹配,如果没有匹配,就不存在该成员

查找

void SearchContact(Contact* ps)//查找联系人
{
	int pos = PanDuan(ps);
	if (pos == 0)
	{
		return;
	}
	if (pos == ps->sz)
	{
		printf("没有你要查找的联系人!\n");
		return;
	}
	printf("查找成功!,此人的信息如下:\n");
	printf("%-5s\t%-4s\t%-4s\t%-15s\n", "姓名", "年龄", "性别", "电话");
	printf("%-5s\t%-4d\t%-4s\t%-15s\n", ps->data[pos].name, ps->data[pos].age, ps->data[pos].sex, ps->data[pos].tele);
}

  • 通过panduan接口的复用,来查找联系人

修改联系人

void ModifContact(Contact* ps)//修改联系人的信息
{
	int pos = PanDuan(ps);
	if (pos == 0)
	{
		return;
	}
	if (pos == ps->sz)
	{
		printf("没有你要修改的联系人!\n");
		return;
	}
	printf("查找成功,请修改他的信息:\n");
	printf("请输入联系人的姓名:");
	scanf("%s", ps->data[pos].name);
	printf("请输入联系人的年龄:");
	scanf("%d", &(ps->data[pos].age));
	printf("请输入联系人的性别:");
	scanf("%s", ps->data[pos].sex);
	printf("请输入联系人的电话:");
	scanf("%s", ps->data[pos         ].tele);
	printf("修改成功!\n");
}

  • 通过panduan接口复用,来重新修改数据

删除联系人

void DelContact(Contact* ps)//删除联系人的信息
{
	int pos = PanDuan(ps);
	if (pos == 0)
	{
		return;
	}
	if (pos == ps->sz)
	{
		printf("没有你要删除的联系人信息!\n");
		return;
	}
	int j = pos;
	for (j = pos; j < ps->sz - 1; j++)
	{
		ps->data[j] = ps->data[j + 1];
	}
	ps->sz--;
	printf("删除成功!\n");
}

  • 原理:将目标位置之后的数据,覆盖到pos,也就是在pos之后的数据,全部往前挪一位

排序

int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* ps)//排序
{
	qsort(ps->data, ps->sz,sizeof(PeoInfo), cmp_name);
	printf("排序成功!\n");
}


  • 这个在qsort 那边有教学,可以去查阅一下

清空通讯录

void EmptyContact(Contact* ps)//清空
{
	ps->sz = 0;
	printf("清空成功!\n");
}


保存文件和读取文件

void SaveContact(Contact* ps)
{
	FILE*pf = fopen("G:\\c_demo\\Contact.dat", "w");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	//写文件
	int i = 0;
	for (i = 0; i < ps->sz; i++)
	{
		fwrite(ps->data + i, sizeof(PeoInfo), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}
void ReadContact(Contact* ps)
{
	FILE* pf = fopen("G:\\c_demo\\Contact.dat", "r");
	if (pf == NULL)
	{
		perror("LoadContact");
		return;
	}
	//读文件
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		//是否需要增容
		CheakConTact(ps);
		ps->data[ps->sz] = tmp;
		ps->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}
  • 利用fwrite和fread来存储和读取数据

销毁通讯录

void DestroyContact(Contact* ps)
{
	assert(ps);
	free(ps->data);
	ps->data = NULL;
	ps->sz = 0;
	ps->capicity = 0;
}

完整的实现代码

#include "contact.h"

void InitContact(Contact* ps)
{
	ps->data = (int*)malloc(sizeof(PeoInfo) * Init_contact);
	if (ps->data == NULL)
	{
		perror("malloc:");
		return;
	}
	ps->sz = 0;
	ps->capicity = Init_contact;
	ReadContact(ps);//如果之前就已经有数据,加载

}

void CheakConTact(Contact* ps)
{
	if (ps->sz == ps->capicity)
	{
		int* ptr = (int*)realloc(ps->data, sizeof(PeoInfo) * (ps->capicity + Init_contact));
		if (ptr == NULL)
		{
			perror("realloc:");
			return;
		}
		else
		{
			ps->data = ptr;
		}
		printf("增容成功!\n");
		ps->capicity += Init_contact;
	}
}

void AddContact(Contact* ps)//增加联系人的信息
{
	assert(ps);
	CheakConTact(ps);//先检查是否需要增容
	printf("请输入联系人的姓名:");
	scanf("%s", ps->data[ps->sz].name);
	printf("请输入联系人的年龄:");
	scanf("%d", &(ps->data[ps->sz].age));
	printf("请输入联系人的性别:");
	scanf("%s", ps->data[ps->sz].sex);
	printf("请输入联系人的电话:");
	scanf("%s", ps->data[ps->sz].tele);
	ps->sz++;
	printf("添加成功!\n");
}

void ShowContact(Contact* ps)//显示所有联系人
{
	if (ps->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	int i = 0;
	printf("%-5s\t%-4s\t%-4s\t%-15s\n", "姓名", "年龄", "性别", "电话");//水平制表符,左对齐
	for (i = 0; i < ps->sz; i++)
	{
		printf("%-5s\t%-4d\t%-4s\t%-15s\n", ps->data[i].name, ps->data[i].age, ps->data[i].sex, ps->data[i].tele);
	}
}

int PanDuan(Contact* ps)//判断有没有此联系人
{
	if (ps->sz == 0)
	{
		printf("通讯录为空!\n");
		return 0;
	}
	char name[MAX_NAME];
	printf("请输入你要查找的联系人的姓名:");
	scanf("%s", name);
	int i = 0;
	for (i = 0; i < ps->sz; i++)
	{
		if (strcmp(ps->data[i].name, name) == 0)
		{
			break;
		}
	}
	return i;
}

void SearchContact(Contact* ps)//查找联系人
{
	int pos = PanDuan(ps);
	if (pos == 0)
	{
		return;
	}
	if (pos == ps->sz)
	{
		printf("没有你要查找的联系人!\n");
		return;
	}
	printf("查找成功!,此人的信息如下:\n");
	printf("%-5s\t%-4s\t%-4s\t%-15s\n", "姓名", "年龄", "性别", "电话");
	printf("%-5s\t%-4d\t%-4s\t%-15s\n", ps->data[pos].name, ps->data[pos].age, ps->data[pos].sex, ps->data[pos].tele);
}

void ModifContact(Contact* ps)//修改联系人的信息
{
	int pos = PanDuan(ps);
	if (pos == 0)
	{
		return;
	}
	if (pos == ps->sz)
	{
		printf("没有你要修改的联系人!\n");
		return;
	}
	printf("查找成功,请修改他的信息:\n");
	printf("请输入联系人的姓名:");
	scanf("%s", ps->data[pos].name);
	printf("请输入联系人的年龄:");
	scanf("%d", &(ps->data[pos].age));
	printf("请输入联系人的性别:");
	scanf("%s", ps->data[pos].sex);
	printf("请输入联系人的电话:");
	scanf("%s", ps->data[pos].tele);
	printf("修改成功!\n");
}

void DelContact(Contact* ps)//删除联系人的信息
{
	int pos = PanDuan(ps);
	if (pos == 0)
	{
		return;
	}
	if (pos == ps->sz)
	{
		printf("没有你要删除的联系人信息!\n");
		return;
	}
	int j = pos;
	for (j = pos; j < ps->sz - 1; j++)
	{
		ps->data[j] = ps->data[j + 1];
	}
	ps->sz--;
	printf("删除成功!\n");
}

int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* ps)//排序
{
	qsort(ps->data, ps->sz, sizeof(PeoInfo), cmp_name);
	printf("排序成功!\n");
}

void EmptyContact(Contact* ps)//清空
{
	ps->sz = 0;
	printf("清空成功!\n");
}

void SaveContact(Contact* ps)
{
	FILE* pf = fopen("G:\\c_demo\\Contact.dat", "w");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	//写文件
	int i = 0;
	for (i = 0; i < ps->sz; i++)
	{
		fwrite(ps->data + i, sizeof(PeoInfo), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

void ReadContact(Contact* ps)
{
	FILE* pf = fopen("G:\\c_demo\\Contact.dat", "r");
	if (pf == NULL)
	{
		perror("LoadContact");
		return;
	}
	//读文件
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		//是否需要增容
		CheakConTact(ps);
		ps->data[ps->sz] = tmp;
		ps->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

void DestroyContact(Contact* ps)
{
	assert(ps);
	free(ps->data);
	ps->data = NULL;
	ps->sz = 0;
	ps->capicity = 0;
}

总结

  • 动态增长持久化通讯录,大家可以手动敲一下,C语言内容就此告一段落,之后会更新数据结构与算法篇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2072037.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

游戏开发设计模式之组件模式

目录 组件模式在游戏开发中的具体应用案例是什么&#xff1f; 如何在Unity引擎中实现和优化组件模式&#xff1f; 组件模式与其他设计模式&#xff08;如观察者模式、状态模式&#xff09;在游戏开发中的比较优势在哪里&#xff1f; 组件模式 观察者模式 状态模式 综合比…

【python】OpenCV—Single Human Pose Estimation

文章目录 1、Human Pose Estimation2、模型介绍3、基于图片的单人人体关键点检测4、基于视频的单人人体关键点检测5、左右校正6、关键点平滑7、涉及到的库函数scipy.signal.savgol_filter 8、参考 1、Human Pose Estimation Human Pose Estimation&#xff0c;即人体姿态估计&…

通过主成分分析实现检测金融中的异常交易模式

主成分分析&#xff08;PCA&#xff09;是一种在机器学习和数据科学中广泛使用的降维技术。它的主要目的是将高维数据转换为低维数据&#xff0c;同时尽可能保留原始数据中的信息。以下是PCA的一些关键点&#xff1a; 1. 基本概念&#xff1a;PCA的核心思想是将n维特征映射到k维…

5步实现猫眼电影爬虫与k-means算法可视化分析

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

C#二叉搜索树算法

二叉搜索树算法实现原理 二叉搜索树&#xff08;Binary Search Tree&#xff0c;简称BST&#xff09;是一种节点有序排列的二叉树数据结构。它具有以下性质&#xff1a; 每个节点最多有两个子节点。 对于每个节点&#xff0c;其左子树的所有节点值都小于该节点值&#xff0c;…

MySQL数据库连接超时问题排查报告

1、问题描述 边端设备访问云端过程中有概率出现MySQL数据库连接超时报错&#xff0c;具体报错代码如下&#xff1a; [2024-08-13 13:47:44,036] ERROR in app: Exception on /est-tasks/start [POST] Traceback (most recent call last): File "/usr/local/lib/python3.1…

Java 入门指南:Map 接口

Map 接口是 Java 集合框架中的一个接口&#xff0c;它表示了一种键值对的映射关系。Map 接口提供了一种以键为索引的数据结构&#xff0c;通过键可以快速查找对应的值。在 Map 中&#xff0c;每个键只能对应一个值&#xff0c;键是唯一的&#xff0c;但值可以重复。 常用的实现…

在vscode上便捷运行php文件

目录 前言 1. 准备工作 2. 创建文件 3. 下载插件 4.设置访问配置文件 5. 配置默认浏览器 6. 进行验证 前言 对于学习安全的我们来说,部署环境,靶场,和配置环境都是习以为常的一件事情,平时访问靶场都是通过小皮来,今天突想着最近需要对一些漏洞的原理进行研究,所以需要能够…

ESP-WHO C++程序分析基础(七)

以按键部分的程序做为分析基础 先看app_button.hpp文件&#xff0c;文件的路径如下 examples/esp32-s3-eye/main/include/app_button.hpp // AppButton 类&#xff0c;继承自 Subject 类&#xff0c;表示应用程序按钮 首先是先定义了一个 appbutton的按键类&#xff0c;这个…

【计算机组成原理】汇总三、存储系统

三、存储系统&#xff08;存储器层次结构&#xff09; 文章目录 三、存储系统&#xff08;存储器层次结构&#xff09;1.存储器的分类1.1按在计算机中的作用&#xff08;层次&#xff09;❗多级存储结构&#xff08;层次化结构&#xff09;1.2按存储介质1.3按存取方式1.4按信息…

抢单源码修正版,带教程,自动抓取订单,十几种语言可自动切换

亚马逊抢单源码自动抓取订单任务邀请英文,西班牙语可自动切换语言亲测修正版。带完整开源的前后台。 西班牙,英文&#xff0c;巴西&#xff0c;中文&#xff0c;德国&#xff0c;拉法兰西&#xff0c;荷兰&#xff0c;缅甸&#xff0c;Sverige&#xff0c;日本&#xff0c;Trk…

C_02基础学习

c 语言 基础 gcc编译器 作用: 将代码文件编译为可执行文件 分类: 一步到位gcc 要编译的代码文件 -o 生成的可执行文件注意:要编译的代码文件可以是多个-o 生成的可执行文件:可以忽略不写,默认生成a.out文件 分步实现预编译:头文件展示,宏替换,选择型编译gcc -E 要编译的代码…

VMware NET Service在虚拟机关闭后仍然占用CPU - 解决方案

问题 VMware NET Service&#xff08;即vmnat.exe&#xff09;在虚拟机关闭后仍然占用CPU&#xff0c;这是VM 17.5.0 和 VM 17.5.1 软件本身存在的Bug&#xff0c;此问题已在 VM 17.5.2 版本修复&#xff0c;下文介绍解决方案。 时间&#xff1a;2024年8月 解决方案 临时方…

百度网盘网页提示页面过期请刷新 - 解决方案

问题 当打开百度网盘网页的分享链接后&#xff0c;点击下载会提示页面过期请刷新&#xff0c;点击保存到网盘没有响应&#xff0c;刷新后存在同样问题。 原因 这通常是因为浏览器中安装了屏蔽广告的插件&#xff0c;此插件不只拦截了百度网盘的广告&#xff0c;还拦截了一部…

零基础构建 AI 大模型数字人:开启智能交互新时代

人工智能技术的飞速发展&#xff0c;数字人正逐渐成为连接虚拟与现实世界的桥梁。无论是作为客户服务代表、教育助手还是娱乐伙伴&#xff0c;数字人都以其独特的方式丰富着我们的生活。今天&#xff0c;我们将介绍一个基于Dify生态系统的开源数字人技术框架——awesome-digita…

iis部署服务时,发现只能进行get请求,无法发起post、put请求

问题描述&#xff1a; iis部署服务时&#xff0c;发现只能进行get请求&#xff0c;无法发起post、put请求 问题原因&#xff1a; iis部署时&#xff0c;webDAV模块限制 解决方法&#xff1a; 1.搜索【服务器管理器】 2.点击【删除角色功能】 3.选中WebDAV&#xff0c;点…

MinIO实战攻略:轻松构建私有云存储解决方案

OSS 简介 OSS&#xff08;Object Storage Service&#xff09;通常指的是对象存储服务&#xff0c;它是一种数据存储架构&#xff0c;用于存储和检索非结构化数据&#xff0c;如图片、视频、文档和备份等。对象存储服务与传统的块存储和文件存储不同&#xff0c;它将数据作为对…

用户画像标签服务设计

背景 用户画像中不论是实时标签还是离线标签&#xff0c;对需要对外提供查询服务&#xff0c;以便外部接口可以重新用户的标签&#xff0c;本文就来看一下用户标签服务的设计 用户标签服务设计 不论是离线标签还是实时标签&#xff0c;我们都需要先把他们从hive表或者实时re…

OpenCV(第二关--读取图片和摄像头)实例+代码

以下内容&#xff0c;皆为原创&#xff0c;制作不易&#xff0c;感谢大家的关注和点赞。 一.读取图片 我们来读取图片&#xff0c;当你用代码读取后&#xff0c;可能会发现。怎么跟上传的图片颜色有些许的不一样。因为OpenCV的颜色通道是BGR&#xff0c;而我们平常用的matplotl…

华为云通过自定义域名访问桶内对象

问题&#xff1a;通过将自定义域名绑定至OBS桶实现在线预览文件 例如index.html入口文件 且记 自定义域名绑定暂时不支持HTTPS访问方式&#xff0c;只支持HTTP访问方式 自定义域名就先不用部署https证书。 配置完毕之后&#xff0c;将obs桶设置为公开的即可访问 如何在浏览…