通讯录动态+文件版本

server/2024/10/20 10:14:01/

通讯录

  • 前言
    • 初始化通讯录
    • 增加联系人
    • 展示通讯录
    • 查找联系人
    • 删除联系人
    • 修改联系人
    • 排序
    • 加载文件到通讯录
    • 保存通讯录到文件
    • 销毁通讯录
  • 源代码
  • 文末

前言

🎊个人主页:https://blog.csdn.net/2401_83251330?spm=1000.2115.3001.5343
🎀 🎉欢迎大家点赞👍收藏⭐文章
✌️ 🤞 🤟 🤘 🤙 👈 👉 👆 🖕 👇 ☝️ 👍

• 通讯录是底层是数组实现的,我们要在通讯录增删查改等功能,通过这些功能,我们可以很好的完成对成员信息的存储和查找。需要我们能够熟练的使用c语言,对指针,结构体,数组,动态内存管理等知识,完成通讯录,对数据结构的顺序表也有了一定的帮助

通讯录主逻辑和猜数字和扫雷主函数逻辑相同: https://blog.csdn.net/2401_83251330/article/details/140579897?spm=1001.2014.3001.5501
通讯录test.c主逻辑

void menu()
{printf("****************************************\n");printf("*********1.Add        2.Del     ********\n");printf("*********3.Search     4.Modify  ********\n");printf("*********5.Show       6.Sort    ********\n");printf("*********       0.Exit          ********\n");printf("****************************************\n");
}int main()
{int input;Contact con;//初始化通讯录Initcontact(&con);do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case ADD://AddContact(&con);break;case DEL://DelContact(&con);break;case SEARCH://SearchContact(&con);break;case MODIFY://ModifyContact(&con);break;case SHOW://ShowContact(&con);break;case SORT://Sortcontact(&con);break;case EXIT://SaveContact(&con);//DESTROY(&con);printf("退出通讯录\n");break;default:printf("选择错误:请重新选择:\n");break;}} while (input);
}

• 接着我们先来思考,写一个通讯录的时候,先考虑数据的类型,通讯类的每一个数据类型是一个人的信息,我们可以用一个结构体(PeoInfo)来维护通讯录中人💁 People 的信息;
而要把通讯录里的所有数据串起来,我们是不是还需要一个结构体 (Contact),这个结构体不仅要存放数据类型(PeoInfo),最好成员是指向(PeoInfo)类型的指针,还要有数据的个数(count),每一个PeoInfo都是一个数据。为了让通讯录满了能够自动扩容,动态起来,我们还可以用一个容量(capacity)来实现扩容的效果,这都是由这个结构体维护的。

contact.h结构体数据类型定义和函数声明

#pragma once
#include <stdio.h>
#include <stdlib.h>enum Status
{ADD = 1,DEL,SEARCH,MODIFY,SHOW,SORT,EXIT
};
typedef struct PeoInfo
{char name[20];char sex[10];char tel[13];int age;
}PeoInfo;
typedef struct Contact
{PeoInfo* data;//指向通讯录数据的指针int count;//通讯录的当前大小int capacity;//通讯录的容量
}Contact,*pContact;//初始化通讯录
void Initcontact(pContact pc);//保存通讯录
void SaveContact(pContact pc);//销毁通讯录
void DESTROY(pContact pc);//添加联系人
void AddContact(pContact pc);//展示通讯录
void ShowContact(pContact pc);//删除联系人
void DelContact(pContact pc);//查找联系人
void SearchContact(pContact pc);//修改联系人
void ModifyContact(pContact pc);//排序通讯录
void Sortcontact(pContact pc);//加载文件到通讯录
void LoadContact(pContact pc);

这里声明了我们所要需要函数,下面不再声明,还有宏定义,小编给一点点写,再大家补充,下面我们一一来实现。

初始化通讯录

•下面我们先来定义这两个结构体和函数声明,初始化通讯录为空,即一个成员也没有,这里你也可以初始的时候添加成员。我默认没有成员了。

//初始化通讯录
void Initcontact(pContact pc)
{pc->data = NULL;pc->count = pc->capacity = 0;
}

增加联系人

•想添加联系人就要申请空间,由于小编的通讯录为空,所以需要申请空间,不过申请空间,首先要判断当前容capacity够不够支持我的有效数据count,每次我在添加联系人都需要判断,所以我封装一个函数IncreaseCapacity(),这个函数是用于检查是否需要扩容,如果扩容,ppc->data重新指向已经开辟扩容的空间,这里需要用到realloc():
https://legacy.cplusplus.com/reference/cstdlib/realloc/?kw=realloc
函数来实现扩容。
代码如下:

void IncreaseCapacity(pContact ppc)
{assert(ppc);//增容*2ppc->capacity = ppc->capacity == 0 ? 4 : 2 * ppc->capacity;PeoInfo* ptr = (PeoInfo*)realloc(ppc->data, ppc->capacity *sizeof(PeoInfo));if (ptr == NULL){perror("IncreaseCapacity::fai");return;}ppc->data = ptr;
}
//添加联系人
void AddContact(pContact pc)
{assert(pc);//判断增容if (pc->count == pc->capacity){IncreaseCapacity(pc);printf("增容成功\n");}printf("请输入要添加联系人的名字");scanf("%s", pc->data[pc->count].name);printf("请输入要添加联系人的性别");scanf("%s", pc->data[pc->count].sex);printf("请输入要添加联系人的电话");scanf("%s", pc->data[pc->count].tel);printf("请输入要添加联系人的年龄");scanf("%d", &pc->data[pc->count].age);pc->count++;printf("\n添加成功\n");
}

展示通讯录

然后我们可以展示通讯录:
代码如下:

//展示通讯录
void ShowContact(pContact pc)
{printf("%-20s\t%-10s\t%-15s\t%-5s\t\n", "名字", "性别", "电话", "年龄");for (int i = 0; i < pc->count; i++){printf("%-20s\t%-10s\t%-15s\t%5d\t\n", pc->data[i].name,pc->data[i].sex,pc->data[i].tel,pc->data[i].age);}
}

查找联系人

•查找联系人,只需要遍历整个数组,通过名字比较,这里封装了一个查找方法,对查找以及后续删除,修改联系人都有用。
代码如下:

//查找方法,找到了返回下标,找不到返回-1
int Find_message(pContact ppc,char* name)
{assert(ppc);int i;for (i = 0; i < ppc->count; i++){if (strcmp(ppc->data[i].name, name) == 0)return i;}return -1;
}//查找联系人
void SearchContact(pContact pc)
{assert(pc);char name[20];if (pc->count == 0){printf("通讯录为空,无法查找\n");return;}printf("请输入要查找的人的姓名");scanf("%s", name);int ret = Find_message(pc,name);if ( ret == -1){printf("没有这个联系人\n");}else{printf("查找成功!信息如下\n");printf("%-20s\t%-10s\t%-5s\t%-15s\t\n", "名字", "性别", "电话", "年龄");printf("%-20s\t%-10s\t%-15s%-5d\t\n", pc->data[ret].name,pc->data[ret].sex,pc->data[ret].tel,pc->data[ret].age);}
}

删除联系人

•删除联系人与查找联系人类似,只需要先找到该联系人,调用Find_message()方法,再覆盖元素通过移动数组元素即可完成删除操作。
代码如下:

//删除联系人
void DelContact(pContact pc)
{assert(pc);char name[20];if (pc->count == 0){printf("通讯录为空,无法删除\n");return;}printf("请输入要删除的人的姓名");scanf("%s", name);int ret = Find_message(pc, name);//返回下标if (ret == -1){printf("没有这个联系人\n");}else{for (int i = ret; i < pc->count-1; i++){pc->data[i] = pc->data[i+1];}pc->count--;printf("删除成功\n");}
}

修改联系人

•修改联系人也是需要先找到是否有该联系人,调用Find_message()方法,然后修改信息。
代码如下:

//修改联系人
void ModifyContact(pContact pc)
{assert(pc);char name[20];if (pc->count == 0){printf("通讯录为空,无法修改\n");return;}printf("请输入要修改的人的姓名");scanf("%s", name);int ret = Find_message(pc, name);//返回下标if (ret == -1){printf("没有这个联系人\n");}else{printf("请输入新联系人的名字");scanf("%s", pc->data[ret].name);printf("请输入新联系人的性别");scanf("%s", pc->data[ret].sex);printf("请输入新联系人的电话");scanf("%s", pc->data[ret].tel);printf("请输入新联系人的年龄");scanf("%d", &pc->data[ret].age);printf("修改成功\n");}
}

排序

•排序通讯录,理论上我们可以按照名字,年龄,性别,电话排序,这里用qsort排序方法,可以参照我的qsort函数链接: https://mp.csdn.net/mp_blog/creation/editor/141337645
这里仅排序年龄,其余同理,小伙伴们也可以完成剩下功能的排序方式,代码如下:

int cmp_by_age(const void* e1, const void* e2)
{return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}
//排序通讯录
void Sortcontact(pContact pc)
{//按年龄排序qsort(pc->data, pc->count, sizeof(pc->data[0]), cmp_by_age);printf("排序成功\n");
}

加载文件到通讯录

现在为了让我们的通讯录更加真实,能够切实的保存通讯录中人的信息,而不是直接让操作系统释放掉,所以我们希望能保存。这里使用c语言的文件操作,我们只需要在初始化通讯录时的逻辑,加载文件到通讯录,本质是将文件加载到文件缓冲区,然后通过输入流输入到内存。

代码如下:

//从文件读取内容到内存
void LoadContact(pContact pc)
{FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){perror("LoadContact()::fail");return;}//读取文件PeoInfo tmp;while (fread(&tmp, sizeof(PeoInfo), 1, pf) == 1){//增容if (pc->count == pc->capacity){IncreaseCapacity(pc);}pc->data[pc->count] = tmp;pc->count++;}//关闭文件fclose(pf);pf = NULL;
}

保存通讯录到文件

> •保存通讯录的逻辑在退出通讯录,我们需要在退出通讯录前,将内存区联系人的内容一一保存到文件"contact.txt"中

文件操作代码如下:

//保存通讯录
void SaveContact(pContact pc)
{FILE* pf = fopen("contact.txt", "wb");if (pf == NULL){perror("SaveContact()::fail");return;}//保存文件int i;for (i = 0; i < pc->count; i++){fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);}//关闭文件fclose(pf);pf = NULL;
}

销毁通讯录

我们在调用增容函数时向内存申请了空间,这就需要我们释放,所以我们在退出逻辑,先保存通讯录后再释放申请的那块空间也就是销毁通讯录

销毁通讯录代码如下:

//销毁通讯录
void DESTROY(pContact pc)
{assert(pc);free(pc->data);pc->data = NULL;
}

源代码

contact.h

#pragma once
#define  _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
enum Status
{ADD=1,DEL,SEARCH,MODIFY,SHOW,SORT,EXIT = 0
};
typedef struct PeoInfo
{char name[20];char sex[10];char tel[13];int age;
}PeoInfo;
typedef struct Contact
{PeoInfo* data;//指向通讯录数据的指针int count;//通讯录的当前大小int capacity;//通讯录的容量
}Contact, * pContact;//初始化通讯录
void Initcontact(pContact pc);
//增容
void IncreaseCapacity(pContact ppc);//保存通讯录
void SaveContact(pContact pc);//销毁通讯录
void DESTROY(pContact pc);//添加联系人
void AddContact(pContact pc);//展示通讯录
void ShowContact(pContact pc);//删除联系人
void DelContact(pContact pc);//查找联系人
void SearchContact(pContact pc);//修改联系人
void ModifyContact(pContact pc);//排序通讯录
void Sortcontact(pContact pc);//加载文件到通讯录
void LoadContact(pContact pc);

contact.c

在这里插入代码片#include "contact.h"
//初始化通讯录//从文件读取内容到内存
void LoadContact(pContact pc)
{FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){perror("LoadContact()::fail");return;}//读取文件PeoInfo tmp;while (fread(&tmp, sizeof(PeoInfo), 1, pf) == 1){//增容if (pc->count == pc->capacity){IncreaseCapacity(pc);}pc->data[pc->count] = tmp;pc->count++;}//关闭文件fclose(pf);pf = NULL;
}
void Initcontact(pContact pc)
{assert(pc);pc->data = NULL;pc->count = pc->capacity = 0;//加载文件到通讯录LoadContact(pc);
}void IncreaseCapacity(pContact ppc)
{assert(ppc);//增容*2ppc->capacity = ppc->capacity == 0 ? 4 : 2 * ppc->capacity;PeoInfo* ptr = (PeoInfo*)realloc(ppc->data, ppc->capacity * sizeof(PeoInfo));if (ptr == NULL){perror("IncreaseCapacity::fai");return;}ppc->data = ptr;
}
//添加联系人
void AddContact(pContact pc)
{assert(pc);//判断增容if (pc->count == pc->capacity){IncreaseCapacity(pc);printf("增容成功\n");}printf("请输入要添加联系人的名字");scanf("%s", pc->data[pc->count].name);printf("请输入要添加联系人的性别");scanf("%s", pc->data[pc->count].sex);printf("请输入要添加联系人的电话");scanf("%s", pc->data[pc->count].tel);printf("请输入要添加联系人的年龄");scanf("%d", &pc->data[pc->count].age);pc->count++;printf("\n添加成功\n");
}//展示通讯录
void ShowContact(pContact pc)
{printf("%-20s\t%-10s\t%-15s\t%-5s\t\n", "名字", "性别", "电话", "年龄");for (int i = 0; i < pc->count; i++){printf("%-20s\t%-10s\t%-15s\t%5d\t\n", pc->data[i].name,pc->data[i].sex,pc->data[i].tel,pc->data[i].age);}
}//查找方法,找到了返回下标,找不到返回-1
int Find_message(pContact ppc,char* name)
{assert(ppc);int i;for (i = 0; i < ppc->count; i++){if (strcmp(ppc->data[i].name, name) == 0)return i;}return -1;
}//查找联系人
void SearchContact(pContact pc)
{assert(pc);char name[20];if (pc->count == 0){printf("通讯录为空,无法查找\n");return;}printf("请输入要查找的人的姓名");scanf("%s", name);int ret = Find_message(pc,name);if ( ret == -1){printf("没有这个联系人\n");}else{printf("查找成功!信息如下\n");printf("%-20s\t%-10s\t%-5s\t%-15s\t\n", "名字", "性别", "电话", "年龄");printf("%-20s\t%-10s\t%-15s%-5d\t\n", pc->data[ret].name,pc->data[ret].sex,pc->data[ret].tel,pc->data[ret].age);}
}//删除联系人
void DelContact(pContact pc)
{assert(pc);char name[20];if (pc->count == 0){printf("通讯录为空,无法删除\n");return;}printf("请输入要删除的人的姓名");scanf("%s", name);int ret = Find_message(pc, name);//返回下标if (ret == -1){printf("没有这个联系人\n");}else{for (int i = ret; i < pc->count - 1; i++){pc->data[i] = pc->data[i + 1];}pc->count--;printf("删除成功\n");}
}//修改联系人
void ModifyContact(pContact pc)
{assert(pc);char name[20];if (pc->count == 0){printf("通讯录为空,无法修改\n");return;}printf("请输入要修改的人的姓名");scanf("%s", name);int ret = Find_message(pc, name);//返回下标if (ret == -1){printf("没有这个联系人\n");}else{printf("请输入新联系人的名字");scanf("%s", pc->data[ret].name);printf("请输入新联系人的性别");scanf("%s", pc->data[ret].sex);printf("请输入新联系人的电话");scanf("%s", pc->data[ret].tel);printf("请输入新联系人的年龄");scanf("%d", &pc->data[ret].age);printf("修改成功\n");}
}int cmp_by_age(const void* e1, const void* e2)
{return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}
//排序通讯录
void Sortcontact(pContact pc)
{//按年龄排序qsort(pc->data, pc->count, sizeof(pc->data[0]), cmp_by_age);printf("排序成功\n");
}//保存通讯录
void SaveContact(pContact pc)
{assert(pc);FILE* pf = fopen("contact.txt", "wb");if (pf == NULL){perror("SaveContact()::fail");return;}//保存文件int i;for (i = 0; i < pc->count; i++){fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);}//关闭文件fclose(pf);pf = NULL;
}//销毁通讯录
void DESTROY(pContact pc)
{assert(pc);free(pc->data);pc->data = NULL;
}

test.c

#include "contact.h"void menu()
{printf("****************************************\n");printf("*********1.Add        2.Del     ********\n");printf("*********3.Search     4.Modify  ********\n");printf("*********5.Show       6.Sort    ********\n");printf("*********       0.Exit          ********\n");printf("****************************************\n");
}int main()
{int input;Contact con;//初始化通讯录Initcontact(&con);do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case SHOW:ShowContact(&con);break;case SORT:Sortcontact(&con);break;case EXIT:SaveContact(&con);DESTROY(&con);printf("退出通讯录\n");break;default:printf("选择错误:请重新选择:\n");break;}} while (input);
}

文末

通讯录的动态+文件版本小编给大家在这里实现了,通过结构体Contact来维护通讯录,通过PeoInfo来维护联系人的信息,这都是通过结构体和指针来维护的,希望能加深大家的理解,如果本片文章有什么不严谨的地方希望小伙伴们指出,你的三连👨🏽‍❤️‍👨🏻就是我优质文章的动力,谢谢大家啦。
😀 😃 😄 😁 😆 😛 😝 😜 🤪


http://www.ppmy.cn/server/127380.html

相关文章

macOS编译和运行prometheus2.54

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文详述了在macOS(M2芯片)上编译和运行prometheus2.54版本的过程&#xff0c;以及安装node_exporter和grafana并使用prometheus指标进行展示 本地…

FastAPI: websocket的用法及举例

1. Websocket 1.1 Websocket介绍 WebSocket 是一种在单个TCP连接上进行全双工通信的协议&#xff0c;允许客户端和服务器之间相互发送数据&#xff0c;而不需要像传统的HTTP请求-响应模型那样频繁建立和断开连接。 全双工通信(Full-Duplex Communication)是一种通信模式&#…

RabbitMQ的应用问题

一、幂等性保障 幂等性是数学和计算机科学中某些运算的性质, 它们可以被多次应⽤, ⽽不会改变初始应⽤的结果 数学上的幂等性: f(x)=f(f(x)) |x| 数据库操作幂等性: 数据库的 select 操作. 不同时间两次查询的结果可能不同, 但是这个操作是符合幂等性的. 幂等性指的是对资…

Windows环境 源码编译 FFmpeg

记录一下windows环境纯代码编译ffmeg的过程&#xff01; 目录 一、安装MSYS2 1.下载安装 2.配置 3.修改源 4.测试与更新 二、安装其他必要工具 1.安装MinGW-w64 2.安装git 3..安装make等工具 4.编译前的其他准备工作 ①.重命名link.exe ②.下载和安装YASM ③.安装…

小程序原生-利用setData()对不同类型的数据进行增删改

1. 声明和绑定数据 wxml文件 <view> {{school}} </view> <view>{{obj.name}}</view> <view id"{{id}}" > 绑定属性值 </view> <checkbox checked"{{isChecked}}"/> <!--算数运算--> <view>{{ id …

爬虫及数据可视化——运用Hadoop和MongoDB数据进行分析

作品详情  运用Hadoop和MongoDB对得分能力数据进行分析&#xff1b;  运用python进行机器学习的模型调理&#xff0c;利用Pytorch框架对爬取的评论进行情感分析预测&#xff1b;  利用python和MySQL对网站的数据进行爬取、数据清洗及可视化。

大数据毕业设计选题推荐-电影数据分析系统-数据可视化-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

(undone) MIT6.824 Lab1

参考&#xff1a;http://nil.csail.mit.edu/6.824/2021/labs/lab-mr.html task1: 熟悉讲义&#xff0c;尤其是搞明白如何运行测试程序(完成) ------------------------------------------------ start 先看 Introduction 我们的目标&#xff1a;构建一个MapReduce系统。 细节&…