C语言实现通讯录,包括增删改查以及动态开辟内存,写入文件等功能

文章目录

  • 前言
  • 一、注意
  • 二、源码
    • 1. test.c源文件
    • 2. contact.h头文件
    • 3. contact.c源文件
  • 总结


前言

C语言实现通讯录,包括增删改查以及动态开辟内存,写入文件等功能

一、注意

  • 在通讯录菜单栏使用枚举
  • 定义PeoInfo类型时,每个结构体类型的成员也使用枚举来确定长度
  • 刚开始动态开辟3个PeoInfo类型的内存
  • 若通讯录满员,则每次动态开辟2个PeoInfo类型的内存
  • 每次退出通讯录,都会将现在已经存在的通讯录内容写入当前目录下的.txt文件
  • 每次重新进入通讯录,在初始化阶段会自动读取.txt文件,并存放到内存中,若内存不足,会自动增容

二、源码

1. test.c源文件

#define  _CRT_SECURE_NO_WARNINGS#include "contact.h"enum
{QUIT,ADD,DEL,MODIFY,SEARCH,SHOW,SORT
};void menu()
{printf("*******************************\n");printf("***** 1. Add    2. Del   ******\n");printf("***** 3. Modify 4. Search *****\n");printf("***** 5. Show   6. Sort   *****\n");printf("***** 0. Quit             *****\n");printf("*******************************\n");}int main()
{int input = 0;// 创建变量Contact con = { 0 };// 初始化通讯录信息InitContact(&con);do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case MODIFY:ModifyContact(&con);break;case SEARCH:SearchContact(&con);break;case SHOW:ShowContact(&con);break;case SORT:SortContact(&con);break;case QUIT:SaveContact(&con);DestoryContact(&con);printf("退出通讯录!!!\n");break;default :printf("输入错误!!!\n");break;}} while (input);return 0;
}

2. contact.h头文件

#pragma once#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>enum
{MAX_NAME = 20,MAX_SEX = 5,MAX_TELE = 12,MAX_ADDR = 30,DEFAULT_SZ = 3,INC_SZ = 2
};typedef struct PeoInfo
{char name[MAX_NAME];char sex[MAX_SEX];char tele[MAX_TELE];char addr[MAX_ADDR];int age;
}PeoInfo;typedef struct Contact
{PeoInfo* data;int count; // 人物数量int capacity; // 通讯录容量
}Contact;// 初始化通讯录信息
void InitContact(Contact* ps);// 增加通讯录信息
void AddContact(Contact* ps);// 删除通讯录信息
void DelContact(Contact* ps);// 显示通讯录信息
void ShowContact(Contact* ps);// 修改通讯录信息
void ModifyContact(Contact* ps);// 查找指定联系人信息
void SearchContact(Contact* ps);// 排序通讯录
void SortContact(Contact* ps);// 释放开辟空间
void DestoryContact(Contact* ps);// 保存通讯录信息
void SaveContact(Contact* ps);// 加载通讯录信息
void LoadContact(Contact* ps);

3. contact.c源文件

#define  _CRT_SECURE_NO_WARNINGS#include "contact.h"void CheckCap(Contact* ps)
{if (ps->count == ps->capacity){PeoInfo* tmp = (PeoInfo*)realloc(ps->data, (INC_SZ + ps->capacity) * sizeof(PeoInfo));if (NULL == tmp){perror("realloc");return;}ps->data = tmp;tmp = NULL;ps->capacity += INC_SZ;printf("增容成功!!!\n");}
}void LoadContact(Contact* ps)
{FILE* pfread = fopen("contact.txt", "rb");if (pfread == NULL){perror("LoadContact");return;}PeoInfo tmp = { 0 };while (fread(&tmp, sizeof(PeoInfo), 1, pfread) == 1){CheckCap(ps);ps->data[ps->count] = tmp;ps->count++;}fclose(pfread);pfread = NULL;
}// 初始化信息函数
void InitContact(Contact* ps)
{assert(ps);ps->capacity = DEFAULT_SZ;ps->count = 0;ps->data = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));if (ps->data == NULL){perror("InitContact");return;}// 加载到通讯录中LoadContact(ps);
}// 增加信息函数
void AddContact(Contact* ps)
{assert(ps);// 判断增容CheckCap(ps);// 增加内容printf("请输入姓名:>");scanf("%s", ps->data[ps->count].name);printf("请输入年龄:>");scanf("%d", &(ps->data[ps->count].age));printf("请输入性别:>");scanf("%s", ps->data[ps->count].sex);printf("请输入电话:>");scanf("%s", ps->data[ps->count].tele);printf("请输入住址:>");scanf("%s", ps->data[ps->count].addr);ps->count++;printf("添加成功!!!\n");}int FindByName(Contact* ps)
{char name[MAX_NAME];printf("请输入要操作人的姓名:");scanf("%s", name);int i = 0;for (i = 0; i < ps->count; i++){if (strcmp(ps->data[i].name, name) == 0){return i;}}return -1;
}// 删除信息函数
void DelContact(Contact* ps)
{assert(ps);if (ps->count == 0){printf("通讯录为空,无法删除!!!\n");return;}// 根据名字找信息int pos = FindByName(ps);if (-1 == pos){printf("要删除的信息不存在!!!\n");return;}int i = 0;for (i = pos; i < ps->count; i++){ps->data[i] = ps->data[i + 1];}ps->count--;printf("删除成功!!!\n");
}// 显示通讯录信息函数
void ShowContact(Contact* ps)
{assert(ps);printf("%-20s %-5s %-5s %-12s %-30s\n", "名字", "年龄", "性别", "电话", "地址");int i = 0;for (i = 0; i < ps->count; i++){printf("%-20s %-5d %-5s %-12s %-30s\n", ps->data[i].name, ps->data[i].age, ps->data[i].sex, ps->data[i].tele, ps->data[i].addr);}
}// 修改通讯录信息
void ModifyContact(Contact* ps)
{assert(ps);int pos = FindByName(ps);if (-1 == pos){printf("要修改的人信息不存在!!!\n");return;}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("请输入住址:>");scanf("%s", ps->data[pos].addr);printf("修改信息成功!!!\n");
}// 查找指定联系人信息函数
void SearchContact(const Contact* ps)
{assert(ps);int pos = FindByName(ps);if (-1 == pos){printf("要查中的联系人不存在!!!\n");return;}printf("%-20s %-5s %-5s %-12s %-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s %-5d %-5s %-12s %-30s\n", ps->data[pos].name,ps->data[pos].age,ps->data[pos].sex,ps->data[pos].tele,ps->data[pos].addr);
}int cmp_by_name(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}// 排序通讯录函数
void SortContact(Contact* ps)
{assert(ps);qsort(ps->data, ps->count, sizeof(PeoInfo), cmp_by_name);printf("排序成功!!!\n");
}// 释放开辟空间函数
void DestoryContact(Contact* ps)
{assert(ps);free(ps->data);ps->data = NULL;
}// 保存通讯录信息函数
void SaveContact(Contact* ps)
{FILE* pfwrite = fopen("contact.txt", "wb");if (pfwrite == NULL){perror("SaveContact");}int i = 0;for (i = 0; i < ps->count; i++){fwrite(ps->data+i, sizeof(PeoInfo), 1, pfwrite);}fclose(pfwrite);pfwrite = NULL;
}

总结

C语言实现通讯录,包括增删改查以及动态开辟内存,写入文件等功能

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

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

相关文章

Java保证字符串唯一(不唯一加数字后缀)

在Java中&#xff0c;如果你有一个字符串列表&#xff0c;并希望确保每个字符串都是唯一的&#xff0c;那么可以通过检查重复项并为重复的字符串添加后缀数字来实现。下面是一个示例代码&#xff0c;展示了如何操作字符串以确保不重复&#xff1a; import java.util.;public cl…

手撸XXL-JOB(一)——定时任务的执行

SpringBoot执行定时任务 对于定时任务的执行&#xff0c;SpringBoot提供了三种创建方式&#xff1a; 1&#xff09;基于注解(Scheduled) 2&#xff09;基于接口&#xff08;SchedulingConfigurer&#xff09; 3&#xff09;基于注解设定多线程定时任务 基于Scheduled注解 首…

基于51单片机的冰箱控制系统设计( proteus仿真+程序+设计报告+原理图+讲解视频)

基于51单片机冰箱控制系统设计( proteus仿真程序设计报告原理图讲解视频&#xff09; 基于51单片机冰箱控制系统设计 1. 主要功能&#xff1a;2. 讲解视频&#xff1a;3. 仿真4. 程序代码5. 设计报告6. 原理图7. 设计资料内容清单&&下载链接资料下载链接&#xff1a; …

【C++】学习笔记——继承_2

文章目录 十二、继承5. 继承与友元6. 继承与静态成员7. 复杂的菱形继承及菱形虚拟继承 未完待续 十二、继承 5. 继承与友元 友元关系不能继承&#xff0c;也就是说父类友元不能访问子类私有和保护成员 。除非子类也设置成友元。 6. 继承与静态成员 父类定义了 static 静态成…

pnpm:无法加载文件 C:\Users\PC\AppData\Roaming\npm\pnpm.ps1,因为在此系统上禁止运行脚本。

使用pnpm命令启动vue时报了个错&#xff1a; 解决起来也简单&#xff0c;右击开始菜单&#xff0c;用管理员身份打开终端。win11的如下图&#xff1a; win10我记得应该是PowerShell&#xff08;管理员&#xff09;&#xff0c;这样的。 打开之后执行命令&#xff1a; set-…

HOW - 如何封装一个规范的请求

封装一个规范的请求通常涉及到以下几个方面: 请求方法(GET、POST 等)请求参数构造(根据使用的请求库,包括不同 Method 要求的 params 格式、空值处理等)格式转换(如请求体和返回体参数的下划线格式和驼峰格式转换,一般前端会用驼峰命名格式,后台会用下划线命名格式)请…

物联网平台之单体架构

介绍本文主要介绍平台的单体架构&#xff0c;包括各个组件之间的数据流描述以及所做的一些架构选择。在单体架构模式下&#xff0c;所有 ThingsKit 组件都在单个 Java 虚拟机 (JVM) 中启动&#xff0c;并共享相同的操作系统资源。由于 ThingsKit 是用 Java 编写的&#xff0c;因…

蓝队面试题(二)

应急响应基本思路和流程 收集信息:收集客户信息和中毒主机信息,包括样本 判断类型:判断是否是安全事件,何种安全事件,勒索、挖矿、断网、DoS 等等 抑制范围:隔离使受害⾯不继续扩⼤ 深入分析:日志分析、进程分析、启动项分析、样本分析方便后期溯源 清理处置:杀掉…

在Windows环境下的rknn-toolkit环境搭建

在Windows环境下的rknn-toolkit环境搭建 最近需要使用RK3566来跑YOLOv5。想要实现目标就需要使用rknn-toolkit工具将模型转化成可以运行在rk3588的NPU上的模型。只是转换模型的话&#xff0c;没有必要使用GPU&#xff0c;所以我这里安装的是CPU版的&#xff0c;所需的组件按照…

dnf手游攻略,新手入坑必备!

一、角色创建策略 在DNF手游中&#xff0c;角色创建是玩家初入游戏的首要步骤。为最大化游戏体验和收益&#xff0c;新手玩家通常建议创建三个角色&#xff1a;一个主账号和两个副账号。 主账号选择 主账号的选择应基于玩家个人的喜好和对职业的熟悉程度。无论选择哪个职业&a…

番外篇 | 手把手教你利用YOLOv8进行热力图可视化 | 针对视频

前言:Hello大家好,我是小哥谈。YOLOv8的热力图可视化可以帮助我们更加直观地了解模型在图像中的检测情况,同时也可以帮助我们进行模型的调试和优化。热力图是一种颜色渐变的图像,不同颜色的区域表示不同程度的关注度或者置信度。在YOLOv8中,可以通过设置阈值来控制热力图的…

电机控制杂谈——“双采样双更新模式”对模型预测控制/PI控制的提升有多大?

1.采样频率与PWM开关频率的关系 一般有以下两种采样模式。 如下图&#xff08;a&#xff09;所示&#xff0c;这种方式称之为单采单更模式&#xff0c;即在一个PWM周期内&#xff0c;采样一次&#xff0c;更新一次PWM占空比&#xff0c;在这种情况下&#xff0c;采样频率&…

小红书自动私信获客,打造个人品牌

在当今这个内容为王、社交至上的时代&#xff0c;小红书作为新兴的社交电商平台&#xff0c;凭借其独特的社区氛围和强大的种草能力&#xff0c;成为了众多KOL、商家以及个人品牌打造的首选平台。想要在小红书上脱颖而出&#xff0c;精准引流获客&#xff0c;利用自动私信功能不…

【MyBatis】 MyBatis框架下的高效数据操作:深入理解增删查改(CRUD)

文章目录 1. 环境准备2. 增加数据&#xff08;Create&#xff09;3. 查询数据&#xff08;Retrieve&#xff09;4. 更新数据&#xff08;Update&#xff09;5. 删除数据&#xff08;Delete&#xff09;6. 总结 &#x1f389;欢迎来到Java学习路线专栏~探索Java中的静态变量与实…

强化训练:day8(求最小公倍数、数组中的最⻓连续⼦序列、字⺟收集)

文章目录 前言1. 最小公倍数1.1 题目描述1.2 解题思路1.3 代码实现 2. 数组中的最⻓连续⼦序列2.1 题目描述2.2 解题思路2.3 代码实现 3. 字母收集3.1 题目描述3.2 解题思路3.3 代码实现 总结 前言 1. 最小公倍数   2. 数组中的最⻓连续⼦序列   3. 字⺟收集 1. 最小公倍数…

JavaScript中内存泄露的几种情况

在JavaScript开发中&#xff0c;内存泄露是一个常见且可能严重的问题。内存泄露通常发生在程序在不需要某些数据时仍然保留这些数据的引用&#xff0c;导致这些数据无法被垃圾回收机制清除。在长时间运行的Web应用程序或Node.js应用中&#xff0c;内存泄露可能会导致性能下降、…

6-2 递归求Fabonacci数列

作者 C课程组 单位 浙江大学 本题要求实现求Fabonacci数列项的函数。Fabonacci数列的定义如下&#xff1a; f(n)f(n−2)f(n−1) (n≥2)&#xff0c;其中f(0)0&#xff0c;f(1)1。 函数接口定义&#xff1a; int f( int n );函数f应返回第n个Fabonacci数。题目保证输入输出…

JavaEE之线程(5)——Java内存模型、内存可见性、volatile关键字

前言 volatile可以理解成轻量级的 synchronized&#xff0c; 它在多CPU开发中保证了共享变量的“可见性”&#xff0c;可见性我们可以理解成是&#xff1a;当一个线程修改一个共享变量时&#xff0c;另一个线程可以读到这个修改的值。由于它不会引起线程的上下文切换和调度&am…

HTML的使用(中)

文章目录 前言一、HTML表单是什么&#xff1f;二、HTML表单的使用 &#xff08;1&#xff09;<form>...</form>表单标记&#xff08;2&#xff09;<input>表单输入标记总结 前言 在许多网页平台上浏览&#xff0c;大多逃不了登录账号。此时在网页中填写的用户…

Centos 7.9 安装 tigervnc-server

环境&#xff1a;当前使用的 Centos 7.9 的光盘作为的本地源&#xff0c;或使用离线rpm包。 1 检查是否已安装 tigervnc [rootlocalhost /]# rpm -q tigervnc tigervnc-server 未安装软件包 tigervnc tigervnc-server-1.8.0-21.el7.x86_64 如果安装过卸掉 卸载: rpm -e [ro…