通讯录(纯C语言实现)

相信大家都有过通讯录,今天我来带大家实现以下最简单的通讯录,通过本篇文章,相信可以让大家对C语言有进一步的认识。

话不多说,我们先放函数的实现

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"int CheakCapacity(Contact* ps);void LoadContact(Contact* ps)
{FILE* pf = fopen("Contact.dat", "rb");if (pf == NULL){perror("LoadContact");return;}PeoInfo tmp = { 0 };while (fread(&tmp,sizeof(PeoInfo),1,pf)){CheakCapacity(ps);ps->date[ps->size] = tmp;ps->size++;}fclose(pf);pf = NULL;}void InitContact(Contact* ps)
{assert(ps);ps->date = NULL;ps->size = ps->capacity = 0;LoadContact(ps);
}int CheakCapacity(Contact* ps)
{assert(ps);if (ps->capacity == ps->size){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;PeoInfo* tmp = (PeoInfo*)realloc(ps->date, newcapacity * sizeof(PeoInfo));if (tmp == NULL){perror("CheakCapacity");return 0;}else{ps->date = tmp;ps->capacity = newcapacity;printf("增容成功\n");return 1;}}return 1;
}void AddContact(Contact* ps)
{assert(ps);if (CheakCapacity(ps) == 0){return;}printf("请输入增加的姓名:>");scanf("%s", ps->date[ps->size].name);printf("请输入增加的年龄:>");scanf("%d", &ps->date[ps->size].age);printf("请输入增加的性别:>");scanf("%s", ps->date[ps->size].sex);printf("请输入增加的电话:>");scanf("%s", ps->date[ps->size].tele);printf("请输入增加的地址:>");scanf("%s", ps->date[ps->size].addr);ps->size++;printf("增加成功\n");
}void ShowContact(Contact* ps)
{assert(ps);printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");for (int i =0; i<ps->size; i++){printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",ps->date[i].name,ps->date[i].age,ps->date[i].sex,ps->date[i].tele,ps->date[i].addr);}
}int FindByName(const Contact* ps,char name[])
{int i = 0;for (i =0; i<ps->size; i++){if (strcmp(ps->date[i].name,name)==0){return i;}}return -1;
}void DeleteContact(Contact* ps)
{assert(ps);if (ps->size == 0){printf("通讯录为空,无法删除\n");return;}char name[20] = { 0 };printf("请输入你要删除的姓名:>");scanf("%s", name);int ret = FindByName(ps, name);if (ret == -1){printf("要删除的人不存在\n");return;}for (int i =ret; i<ps->size; i++){ps->date[i] = ps->date[i + 1];}ps->size--;printf("删除成功\n");
}void SearchContact(Contact* ps)
{assert(ps);char name[20] = { 0 };printf("请输入你要删除的姓名:>");scanf("%s", name);int pos = FindByName(ps, name);if (pos == -1){printf("要查找的人不存在\n");return;}printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",ps->date[pos].name,ps->date[pos].age,ps->date[pos].sex,ps->date[pos].tele,ps->date[pos].addr);
}void ModifyContact(Contact* ps)
{assert(ps);char name[20] = { 0 };printf("请输入你要修改的姓名:>");scanf("%s", name);int pos = FindByName(ps, name);if (pos == -1){printf("要修改的人不存在\n");return;}printf("请输入修改的姓名:>");scanf("%s", ps->date[pos].name);printf("请输入修改的年龄:>");scanf("%d", &ps->date[pos].age);printf("请输入修改的性别:>");scanf("%s", ps->date[pos].sex);printf("请输入修改的电话:>");scanf("%s", ps->date[pos].tele);printf("请输入修改的地址:>");scanf("%s", ps->date[pos].addr);
}void SortContact(Contact* ps)
{int i = 0;int j = 0;for (i=0; i<ps->size-1; i++){for (j =0; j<ps->size-1-i; j++){if (strcmp(ps->date[j].name, ps->date[j+1].name) > 0){PeoInfo tmp = ps->date[j];ps->date[j] = ps->date[j + 1];ps->date[j + 1] = tmp;}}}printf("排序成功\n");
}void DestoryContact(Contact* ps)
{free(ps->date);ps->date = NULL;ps->capacity = ps->size = 0;
}void SaveContact(Contact* ps)
{FILE* pf = fopen("Contact.dat", "wb");if (pf == NULL){perror("SaveContact");return;}for (int i =0; i<ps->size; i++){fwrite(ps->date+ i, sizeof(PeoInfo), 1, pf);}fclose(pf);pf = NULL;
}

#define  _CRT_SECURE_NO_WARNINGS 1
#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");}void Text()
{int input = 0;Contact con;InitContact(&con);do {menu();printf("请输入你的选择:>");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DeleteContact(&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);DestoryContact(&con);printf("退出通讯录成功\n");break;default:printf("你选择的有误,请重新输入\n");break;}} while (input);
}int main()
{Text();return 0;
}

 是不是看到这里会感到很害怕??不用怕,跟着我的思路,你也可以实现它,我带着你一步一步实现每一个功能

  •  我们要实现这个功能,首先我们来看下面的代码,首先我们应该先选择,这里我选择了do while的语句,要实现这个功能,我们就用到了menu这个函数来打印菜单,其实很简单,我就用了printf函数来实现。
void Text()
{int input = 0;Contact con;InitContact(&con);do {menu();printf("请输入你的选择:>");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DeleteContact(&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);DestoryContact(&con);printf("退出通讯录成功\n");break;default:printf("你选择的有误,请重新输入\n");break;}} while (input);
}

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

  • 我们直接来实现通讯录的基本功能,我先用struct来定义了一个人的基本信息,然后再用struct来包含人的基本信息,但是我还加上了size和capcacity,size是用来记录存储了多少个人,而capacity是用来说明有多少个空间
    typedef struct PeoInfo
    {char name[MAX_NAME];int age;char sex[MAX_SEX];char tele[MAX_TELE];char addr[MAX_ADDR];
    }PeoInfo;typedef struct Contact
    {PeoInfo *date;int size;int capacity;
    }Contact;

  •  我们一开始用通讯录不要忘了要初始化,我在这里是把ps->date指向的空间置位了NULL,size和capacity初始化为0,因为我们是要弄一个动态的通讯录,所以我们特意用结构体的指针date来设计。
  • 我们实现一个通讯录,我们先设想一个场景,如果你的手机关机了,重启后是不是通讯录里面的信息还是存在的,所以我们也要实现这样的功能。
  • 我在这里是用到了文件操作,我先创建了结构体的tmp临时变量,我用fread来操作,如果freaed的返回值不是0,我们就将数据拷贝到tmp中。
  • while (fread(&tmp,sizeof(PeoInfo),1,pf)){CheakCapacity(ps);ps->date[ps->size] = tmp;ps->size++;}

    下面是这个功能的全部代码

  • void LoadContact(Contact* ps)
    {FILE* pf = fopen("Contact.dat", "rb");if (pf == NULL){perror("LoadContact");return;}PeoInfo tmp = { 0 };while (fread(&tmp,sizeof(PeoInfo),1,pf)){CheakCapacity(ps);ps->date[ps->size] = tmp;ps->size++;}fclose(pf);pf = NULL;}void InitContact(Contact* ps)
    {assert(ps);ps->date = NULL;ps->size = ps->capacity = 0;LoadContact(ps);
    }

  •  接着我们来看第二个功能,增加人的信息,我们在一开始增加信息的时候,要想到如果空间满了的话,就要考虑扩容。所以,我一开始就判断是否要扩容,因为一开始size和capacity都是0,所以一开始就要扩容,我是malloc了一个空间,如果满了的话,我就扩二倍。最后通过返回值来判断是否扩容成功了。
int CheakCapacity(Contact* ps)
{assert(ps);if (ps->capacity == ps->size){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;PeoInfo* tmp = (PeoInfo*)realloc(ps->date, newcapacity * sizeof(PeoInfo));if (tmp == NULL){perror("CheakCapacity");return 0;}else{ps->date = tmp;ps->capacity = newcapacity;printf("增容成功\n");return 1;}}return 1;
}
  • 然后,接着实现add函数,其实很简单,我们一开始的size是0,所以每当我们增加一个信息,ps->size就要++,而ps->date指向的就是人信息的那片空间,ps->date【ps->size】后面再加上我们要增加的信息,就完成了我们add函数的功能。

void AddContact(Contact* ps)
{assert(ps);if (CheakCapacity(ps) == 0){return;}printf("请输入增加的姓名:>");scanf("%s", ps->date[ps->size].name);printf("请输入增加的年龄:>");scanf("%d", &ps->date[ps->size].age);printf("请输入增加的性别:>");scanf("%s", ps->date[ps->size].sex);printf("请输入增加的电话:>");scanf("%s", ps->date[ps->size].tele);printf("请输入增加的地址:>");scanf("%s", ps->date[ps->size].addr);ps->size++;printf("增加成功\n");
}


  •  第二个删除的功能,我的思想就是先创建一个数组,然后用数组和通讯录中名字相比较看是否相等。然后返回要删除的下标
int FindByName(const Contact* ps,char name[])
{int i = 0;for (i =0; i<ps->size; i++){if (strcmp(ps->date[i].name,name)==0){return i;}}return -1;
}
  • 最后到删除的操作就是后面往前面移动,然后ps->size--就可以了。
void DeleteContact(Contact* ps)
{assert(ps);if (ps->size == 0){printf("通讯录为空,无法删除\n");return;}char name[20] = { 0 };printf("请输入你要删除的姓名:>");scanf("%s", name);int ret = FindByName(ps, name);if (ret == -1){printf("要删除的人不存在\n");return;}for (int i =ret; i<ps->size; i++){ps->date[i] = ps->date[i + 1];}ps->size--;printf("删除成功\n");
}


  •  第三个search功能的实现,也是和删除差不多的操作,不过我们是查找功能,所以我们最后是直接printf来打印出我们要查找的信息,这里我也用到了FindByName函数的复用。

void SearchContact(Contact* ps)
{assert(ps);char name[20] = { 0 };printf("请输入你要删除的姓名:>");scanf("%s", name);int pos = FindByName(ps, name);if (pos == -1){printf("要查找的人不存在\n");return;}printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",ps->date[pos].name,ps->date[pos].age,ps->date[pos].sex,ps->date[pos].tele,ps->date[pos].addr);
}


  •  第四个修改的功能,因为我们也要找到要修改的下标,所以我用到了函数的复用,我们只要在要修改的下标中重新输入自己想修改的值就可以了。
void ModifyContact(Contact* ps)
{assert(ps);char name[20] = { 0 };printf("请输入你要修改的姓名:>");scanf("%s", name);int pos = FindByName(ps, name);if (pos == -1){printf("要修改的人不存在\n");return;}printf("请输入修改的姓名:>");scanf("%s", ps->date[pos].name);printf("请输入修改的年龄:>");scanf("%d", &ps->date[pos].age);printf("请输入修改的性别:>");scanf("%s", ps->date[pos].sex);printf("请输入修改的电话:>");scanf("%s", ps->date[pos].tele);printf("请输入修改的地址:>");scanf("%s", ps->date[pos].addr);
}


 是不是发现其实函数的实现很多都是相似的, 所以不用怕,接着往后看。

  •  第五个函数:就是我们要展示信息,我们直接用for循环遍历一遍就行了,只不过我们为了好看一点,用到了左对齐,至于长度可以根据你来实现。最后的效果就是下面这样。

void ShowContact(Contact* ps)
{assert(ps);printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");for (int i =0; i<ps->size; i++){printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",ps->date[i].name,ps->date[i].age,ps->date[i].sex,ps->date[i].tele,ps->date[i].addr);}
}


  •  第六个函数:我们要排序名字的大小,这里我直接用了冒泡排序,可以直接把名字的大小排出来。只不过这里的时间复杂度是O(N^2),效率是很低的,也可以用快排来实现,效率可以更高一点
void SortContact(Contact* ps)
{int i = 0;int j = 0;for (i=0; i<ps->size-1; i++){for (j =0; j<ps->size-1-i; j++){if (strcmp(ps->date[j].name, ps->date[j+1].name) > 0){PeoInfo tmp = ps->date[j];ps->date[j] = ps->date[j + 1];ps->date[j + 1] = tmp;}}}printf("排序成功\n");
}


  •  因为我们是动态来实现通讯录的,所以我用到了malloc,在最后退出的时候,也要free掉开辟的空间,我用了一个DestoryContact函数来实现,。
  • void DestoryContact(Contact* ps)
    {free(ps->date);ps->date = NULL;ps->capacity = ps->size = 0;
    }


  • 最后一个函数:是否想过这样的一个问题,在我们输入信息的时候,如果我们退出,信息在下一次打开时还保存着呢???经过学习,我发现文件操作就可以来实现它 。
  • 我是用了fopen来打开一个二进制的文件Contact.dat,用到了for循环fwrite来把已经存在的信息保存在文件流中(也就是这个文件中),又因为一开始初始化的时候,要把文件的信息录进去,这样,我们就实现了信息的保存。
void SaveContact(Contact* ps)
{FILE* pf = fopen("Contact.dat", "wb");if (pf == NULL){perror("SaveContact");return;}for (int i =0; i<ps->size; i++){fwrite(ps->date+ i, sizeof(PeoInfo), 1, pf);}fclose(pf);pf = NULL;
}

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

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

相关文章

高时空分辨率、高精度一体化预测技术之风、光、水能源自动化预测教程

详情点击链接&#xff1a;高时空分辨率、高精度一体化预测技术之风、光、水能源自动化预测 第一&#xff1a;预测平台及安装 一、高精度气象预测基础 综合气象观测数值模拟模式&#xff1b; 全球预测模式、中尺度数值模式&#xff1b; 二、自动化预测平台 Linux系统 Crontab…

记一次rabbitmq消息发送成功,消费丢失问题

记一次rabbitmq消息发送成功&#xff0c;消费丢失问题 背景 测试数据归档&#xff0c;偶现数据未归档 排查 idea线上调试&#xff0c;log日志&#xff0c;数据库消息发送记录&#xff0c;代码分块重复执行看哪块出的问题&#xff0c;结果均无问题&#xff0c;最后使用rabbi…

AI销售工具:驱动销售团队效率和个性化服务的未来

在数字化时代&#xff0c;AI销售工具成为推动销售行业发展的重要力量。这些创新工具融合了人工智能技术和销售流程&#xff0c;以提高销售团队的效率和提供个性化服务为目标。随着科技的不断进步&#xff0c;AI销售工具正引领着销售行业走向一个更加智能和高效的未来。 AI驱动的…

数据结构 ~ 栈、队列

栈 一个后进先出的数据结构、JS中没有栈&#xff0c;可以使用 Array 模拟 const stack [] stack.push(1) // 入栈 stack.push(2) // 入栈 const item1 stack.pop() // 出栈 const item2 stack.pop() // 出栈以上代码可以使用 nodeJs 断点调试&#xff08;F5启动&#xff0…

【Linux】进程信号

文章目录 1. 信号的理解1.1 什么是进程信号1.2 见见进程信号1.3 信号的发送与记录1.4 信号的处理1.4.1 信号的三种处理方式1.4.2 核心转储 2. 信号的产生2.1 终端按键产生信号2.2 系统调用产生信号2.3 软件异常产生信号2.4 硬件异常产生信号 3. 信号的保存3.1 信号其他相关概念…

电子锁语音芯片方案,低功耗声音提示ic,WT588F02B-8S

随着科技的不断发展&#xff0c;电子锁已成为现代社会中&#xff0c;安全性和便利性并存的必备设备。如何为电子锁行业增添智能化、人性化的功能已成为行业内的热门话题。 在这个迅速发展的市场中&#xff0c;深圳唯创知音推出了一款语音交互方案——WT588F02B-8S 低功耗声音提…

UnxUtils工具包,Windows下使用Linux命令

1. 前言 最近写批处理多了&#xff0c;发现Windows下的bat批处理命令&#xff0c;相比Linux的命令&#xff0c;无论是功能还是多样性&#xff0c;真的差太多了。但有时候又不得不使用bat批处理&#xff0c;好在今天发现了一个不错的工具包&#xff1a;UnxUtils&#xff0c;这个…

Python多线程 threading 和多进程 multiprocessing

1. 并发 vs 并行 线程是程序执行的最小单位&#xff0c;一个进程可以由一个或多个线程组成&#xff0c;各个线程之间也是交叉执行。 并发&#xff0c;相当于单核CPU&#xff0c;宏观同时执行&#xff0c;微观高速切换 交替执行。多线程、高并发这些词语更多地出现在服务端程序…

06-C++ 基本算法 - 二分法

&#x1f4d6; 前言 在这个笔记中&#xff0c;我们将介绍二分法这种基本的算法思想&#xff0c;以及它在 C 中的应用。我们将从一个小游戏猜数字开始&#xff0c;通过这个案例来引出二分法的概念。然后我们将详细讲解什么是二分法以及它的套路和应用。最后&#xff0c;我们还会…

在 3ds Max 中创建逼真的玻璃材质

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 尽管本教程基于 3ds Max&#xff0c;但相同的设置适用于许多其他 3D 产品。 注意&#xff1a;单击每个步骤中的缩略图可查看更大的屏幕截图&#xff0c;其中包括视口和用户界面的相关部分。 步骤 1由于本教…

广西学子复读15年,不服从分配。网友:完全是浪费时间

广西学子复读15年&#xff0c;不服从分配。网友&#xff1a;完全是浪费时间 唐尚珺的复读行为引起了网友们的不同解读。有人认为他是一个执念深重的人&#xff0c;目标是考上清华北大&#xff0c;但这个说法是否真实&#xff0c;我们无法确定。无论如何&#xff0c;我们必须认识…

electron+vue3全家桶+vite项目搭建【24】设置应用图标,打包文件的图标

文章目录 引入实现步骤测试结果 引入 demo项目地址 在electron中&#xff0c;我们可以通过electron-builder的配置文件来设置打包后的应用图标 实现步骤 因为mac环境下的图标需要特殊格式&#xff0c;这里我们可以利用electron-icon-builder进行配置 1.引入相关依赖 # 安…

GPT 如此强大,我们可以利用它实现什么?

GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一种基于Transformer结构的预训练语言生成模型&#xff0c;由OpenAI研发。它可以生成高质量的自然语言文本&#xff0c;取得了很好的效果&#xff0c;被广泛应用于各个领域。以下是一些利用GPT实现的应用。 一…

ts中setState的类型

两种方法: 例子: 父组件 const [value, setValue] useState(); <ChildsetValue{setValue} />子组件 interface Ipros {setValue: (value: string) > void } const Child: React.FC<Ipros> (props) > {}

SpringMvc配置静态资源访问路径

文章目录 1. 整体流程2. registry.addResourceHandler()2.1 函数分析2.2 结果演示 3. ResourceHandlerRegistration.addResourceLocations()3.1 函数分析3.2 结果演示 1. 整体流程 1. 写一个配置类继承WebMvcConfigurationSupport 2. 利用 registry.addResourceHandler("…

Vue成绩案例实现添加、删除、显示无数据、添加日期、总分均分以及数据本地化等功能

一、成绩案例 ✅✅✅通过本次案例实现添加、删除、显示无数据、添加日期、总分均分以及数据本地化等功能。 准备成绩案例模板&#xff0c;我们需要在这些模板上面进行功能操作。 <template><div class"score-case"><div class"table">…

nginx基础3——配置文件详解(实用功能篇)

文章目录 一、平滑升级二、修饰符2.1 无修饰符效果2.2 精准匹配&#xff08;&#xff09;2.3 区分大小写匹配&#xff08;~&#xff09;2.4 不区分大小写匹配&#xff08;~*&#xff09;2.5 匹配优先级 三、访问控制四、用户认证五、配置https六、开启状态界面七、rewrite重写u…

matplotlib 3D

import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np# 创建一个三维坐标轴 fig plt.figure() ax fig.add_subplot(221, projection3d) xx fig.add_subplot(222) yy fig.add_subplot(223) xy fig.add_subplot(224)# 生成示例数据…

关于你欠缺的NoSQL中的redis和mongoDB

文章目录 前言一、在string list hash结构中&#xff0c;每个至少完成5个命令&#xff0c;包含插入 修改 删除 查询&#xff0c;list 和hash还需要增加遍历的操作命令1、STRING类型2、List类型数据的命令操作&#xff1a;3、举例说明list和hash的应用场景&#xff0c;每个至少一…

echarts图例对齐

富文本不生效&#xff0c;是没有设置lineHeight