动态版通讯录——“C”
各位CSDN的uu们你们好呀,今天,小雅兰的内容是动态版通讯录啦,其实之前,我就已经写过静态版的通讯录了,只是存在着一些问题,具体细节可以详细看看我的静态版通讯录,好了,话不多说,现在,就让我们进入动态版通讯录的世界吧
静态版通讯录——“C”_认真学习的小雅兰.的博客-CSDN博客
动态内存管理(上)——“C”_认真学习的小雅兰.的博客-CSDN博客
动态的版本
- 默认能够存放3个人的信息
- 不够的话,每次增加两个人的信息
之前写通讯录是这样写的:
typedef struct Contact {PeoInfo data[MAX];//存放数据int sz;//记录通讯录中有效信息的个数 }Contact;现在我们仔细想想,在此结构体中,存放数据采用数组的方式就会有问题啊,所以,要把它改写成指针的形式,另外,我们还需要新定义一个变量,来表示通讯录当前的容量
typedef struct Contact {PeoInfo *data;//data指向了存放数据的空间int sz;//记录通讯录中有效信息的个数int capacity;//通讯录当前的容量 }Contact;这样子改写之后,就可以啦
之前初始化通讯录,是这样写的:
//初始化通讯录 void InitContact(Contact* pc) {pc->sz = 0;memset(pc->data, 0, sizeof(pc->data)); }当然,改为动态版通讯录了,就要修改一下啦,默认容量是3
//初始化通讯录 void InitContact(Contact* pc) {pc->sz = 0;pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));if (pc->data == NULL){printf("通讯录初始化失败:%s\n", strerror(errno));return;}pc->capacity = DEFAULT_SZ; }
扩容:
//扩容 void CheckCapacity(Contact* pc) {if (pc->sz == pc->capacity)//容量和信息数相等时{PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));if (ptr == NULL){printf("CheckCapacity:%s\n", strerror(errno));return;}else{pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功,当前容量:%d\n", pc->capacity);}} }但是这个代码仍然不是很好,我们仔细想想:在增加联系人信息的时候,调用扩容函数,但是,扩容也有可能失败呀,那我们什么也不做的话,那怎么才能知道到底是扩容成功了还是失败了呢?下面,我们对上述代码进行改进,使得扩容函数返回值为int类型
//扩容 //扩容失败,返回0 //扩容成功,或者后面的空间足够,不需要扩容,返回1 int CheckCapacity(Contact* pc) {if (pc->sz == pc->capacity)//容量和信息数相等时{PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));if (ptr == NULL){printf("CheckCapacity:%s\n", strerror(errno));return 0;}else{pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功,当前容量:%d\n", pc->capacity);return 1;}}return 1; }下面这个代码就好多啦
增加联系人信息:
//增加指定联系人 void AddContact(Contact* pc) {if (CheckCapacity(pc) == 0){printf("空间不够,扩容失败\n");return;}else{printf("请输入姓名:>");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->sz].tele);printf("请输入地址:>");scanf("%s", pc->data[pc->sz].addr);pc->sz++;printf("添加成功\n");} }
销毁通讯录:
//销毁通讯录 void DestroyContact(Contact* pc) {free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;printf("释放内存......\n"); }
上述这些改动就是对静态版通讯录的所有改动啦,此动态版通讯录很好地解决了容量问题,但是其实,这个动态版通讯录还是存在着一定的问题,因为:这个动态版通讯录还是不能够保存信息,程序一退出,信息就都没了,那么这个问题又该怎么解决呢?等小雅兰学习到文件的知识点,再来给大家分享分享吧
接下来,附上源代码:
txl.h的内容:
#pragma once
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#define DEFAULT_SZ 3
#define INC_SZ 2
//表示一个人的信息
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 *data;//data指向了存放数据的空间int sz;//记录通讯录中有效信息的个数int capacity;//通讯录当前的容量
}Contact;//初始化通讯录
void InitContact(Contact* pc);//销毁通讯录
void DestroyContact(Contact* pc);//增加指定联系人
void AddContact(Contact* pc);//显示联系人信息
void ShowContact(const Contact* pc);//删除指定联系人
void DelContact(Contact* pc);
//void DelContact(pContact pc);//查找指定联系人
void SearchContact(const Contact* pc);
//void SearchContact(pContact pc);//修改指定联系人
void ModifyContact(Contact* pc);//按照名字来排序
void SortContact(Contact* pc);
txl.c的内容:
#define _CRT_SECURE_NO_WARNINGS 1
#include"txl.h"
//初始化通讯录
void InitContact(Contact* pc)
{pc->sz = 0;pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));if (pc->data == NULL){printf("通讯录初始化失败:%s\n", strerror(errno));return;}pc->capacity = DEFAULT_SZ;
}
//扩容
//扩容失败,返回0
//扩容成功,或者后面的空间足够,不需要扩容,返回1
int CheckCapacity(Contact* pc)
{if (pc->sz == pc->capacity)//容量和信息数相等时{PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));if (ptr == NULL){printf("CheckCapacity:%s\n", strerror(errno));return 0;}else{pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功,当前容量:%d\n", pc->capacity);return 1;}}return 1;
}
//增加指定联系人
void AddContact(Contact* pc)
{if (CheckCapacity(pc) == 0){printf("空间不够,扩容失败\n");return;}else{printf("请输入姓名:>");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->sz].tele);printf("请输入地址:>");scanf("%s", pc->data[pc->sz].addr);pc->sz++;printf("添加成功\n");}
}
//销毁通讯录
void DestroyContact(Contact* pc)
{free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;printf("释放内存......\n");
}
//显示联系人信息
void ShowContact(const Contact* pc)
{int i = 0;//姓名 年龄 性别 电话 地址//zhangsan 13 男 123456 北京//打印标题printf("%-15s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");for (i = 0; i < pc->sz; i++){printf("%-15s %-4d %-5s %-12s %-30s\n", pc->data[i].name,pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);}
}
static int FindByName(const Contact* pc, char name[])
{int i = 0;for (i = 0; i < pc->sz; i++){if (0 == strcmp(pc->data[i].name, name)){return i;}}return -1;
}//删除指定联系人
void DelContact(Contact* pc)
{char name[MAX_NAME] = { 0 };if (pc->sz == 0){printf("通讯录为空,无法删除\n");return;}//删除//1.找到要删除的人 - 位置(下标)printf("输入要删除人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1){printf("要删除的人不存在\n");return;}//2.删除-删除pos位置上的元素int i = 0;for (i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");
}
//查找指定联系人
void SearchContact(const Contact* pc)
{char name[MAX_NAME] = { 0 };printf("请输入要查找的人的名字:>");scanf("%s", name);//查找int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在\n");return;}//打印printf("%-15s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");printf("%-15s %-4d %-5s %-12s %-30s\n", pc->data[pos].name,pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);
}
//修改指定联系人
void ModifyContact(Contact* pc)
{char name[MAX_NAME] = { 0 };printf("请输入要修改人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1){printf("要修改的人不存在\n");return;}//修改printf("请输入姓名:>");scanf("%s", pc->data[pos].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pos].age));printf("请输入性别:>");scanf("%s", pc->data[pos].sex);printf("请输入电话:>");scanf("%s", pc->data[pos].tele);printf("请输入地址:>");scanf("%s", pc->data[pos].addr);printf("修改成功\n");
}
//排序通讯录元素
//按照名字来排序
int cmp_by_name(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);ShowContact(pc);printf("排序成功\n");
}
test.c的内容:
#define _CRT_SECURE_NO_WARNINGS 1
#include"txl.h"
void menu()
{printf("#############################################\n");printf("############# 1.add ############\n");printf("############# 2.del ############\n");printf("############# 3.search ############\n");printf("############# 4.modify ############\n");printf("############# 5.show ############\n");printf("############# 6.sort ############\n");printf("############# 0.exit ############\n");printf("#############################################\n");
}
enum Option
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT
};
int main()
{int input = 0;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:DestroyContact(&con);ShowContact(&con);break;case SORT:SortContact(&con);break;case EXIT:printf("退出通讯录\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}
好啦,小雅兰今天的动态版通讯录的内容就到这里啦,继续加油噢!!!

相关文章:
动态版通讯录——“C”
各位CSDN的uu们你们好呀,今天,小雅兰的内容是动态版通讯录啦,其实之前,我就已经写过静态版的通讯录了,只是存在着一些问题,具体细节可以详细看看我的静态版通讯录,好了,话不多说&…...
SpringBoot 将PDF转成图片或World
SpringBoot 将PDF转成图片或World 准备工作Apache PDFBox将PDF转成一张图片将PDF转成多张图片将PDF转成其他文件格式总结SpringBoot 是一款非常流行的 Java Web 开发框架,可以用来构建各种 Web 应用程序。在本篇博客中,我们将介绍如何使用 SpringBoot 将 PDF 转换成图片或其他…...
JavaScript中的for in和for of的区别(js的for循环)
简述:js中的for循环大家都知道,今天来分享下for in和for of在使用时区别和注意事项,顺便做个笔记; 测试数据 //数组const arr [1, 2, 3, 4, 5]//对象const obj {name: "小李",color: ["plum", "pink&q…...
C++的各种初始化
C的各种初始化 1.默认初始化 默认初始化是指定义变量时没有指定初值时进行的初始化操作。例如int a; Sales_data myData;等等。这些变量被定义了而不是仅仅被声明(因为没有extern关键字修饰),而且没有显式的赋予初值。特别的,如…...
使用Python突破某网游游戏JS加密限制,进行逆向解密,实现自动登录
兄弟们天天看基础看腻了吧 今天来分享一下如何使用Python突破某网游游戏JS加密限制,进行逆向解密,实现自动登录。 逆向目标 目标:某 7 网游登录主页:aHR0cHM6Ly93d3cuMzcuY29tLw接口:aHR0cHM6Ly9teS4zNy5jb20vYXBpL…...
用CSS3画了一只猫
感觉我写得技术含量不高,全都是用绝对定位写的,一定会有更好的,代码量更少的做法吧 <!DOCTYPE html> <html> <head><title>Cute Cat</title><style type"text/css">*{box-sizing: border-box…...
菜鸟刷题Day7
⭐作者:别动我的饭 ⭐专栏:菜鸟刷题 ⭐标语:悟已往之不谏,知来者之可追 一.整理字符串:1544. 整理字符串 - 力扣(LeetCode) 描述 给你一个由大小写英文字母组成的字符串 s 。 一个整理好的字…...
蓝桥杯刷题第二十三天
第一题:长草题目描述小明有一块空地,他将这块空地划分为 n 行m 列的小块,每行和每列的长度都为 1。小明选了其中的一些小块空地,种上了草,其他小块仍然保持是空地。这些草长得很快,每个月,草都会…...
进阶指针(3)——指针与数组笔试题的解析
在讲解之前我们先回顾一下,以下将要涉及的重要知识点: 1、数组名是什么? ①sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节; ②&数组名,这里的数…...
树与二叉树的存储与遍历
文章目录一、树概念二、二叉树三、二叉树的存储与遍历一、树概念 如前面的顺序表,链表,栈和队列都是线性的数据结构,树是非线性的结构。树可以有n个结点,n>0,当n0是就表示树为空 n>0,代表树不为空,不为空的树&am…...
28-队列练习-LeetCode622设计循环队列
题目 设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通…...
你值得拥有——流星雨下的告白(Python实现)
目录1 前言2 霍金说移民外太空3 浪漫的流星雨展示 4 Python代码 1 前言我们先给个小故事,提一下大家兴趣;然后我给出论据,得出结论。最后再浪漫的流星雨表白代码奉上,还有我自创的一首诗。开始啦:2 霍金说移民外太空霍…...
【5G RRC】NR测量事件介绍
博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。 博客…...
PMP项管2023年5月的备考准备攻略!
2023年共有4次PMP考试,分别是3月、5月、8月、11月,由于3月份考试不开放新报名,所以第一次备考PMP的同学可以选择参加5月份考试。那么,现在备考5月份PMP考试还来得及吗? 现在开始备考5月PMP考试,时间是非常…...
Linux进程概念—环境变量
Linux进程概念—环境变量1.孤儿进程2.环境变量2.1常见环境变量2.2查看环境变量方法2.3在环境变量中添加2.4和环境变量相关的命令2.5环境变量的组织方式2.6命令行参数🌟🌟hello,各位读者大大们你们好呀🌟🌟 Ὠ…...
用JS+CSS打造你自己的弹幕王国,让网页动起来!
文章目录前言主要内容实现方法DOM方法显现效果代码CANVAS方法显现效果代码总结更多宝藏前言 😎🥳😎🤠😮🤖🙈💭🍳🍱 用JSCSS打造你自己的弹幕王国,…...
C++ LinuxWebServer 2万7千字的面经长文(上)
⭐️我叫忆_恒心,一名喜欢书写博客的在读研究生👨🎓。 如果觉得本文能帮到您,麻烦点个赞👍呗! 前言 Linux Web Server项目虽然是现在C求职者的人手一个的项目,但是想要吃透这个项目ÿ…...
vue3 解决各场景 loading过度 ,避免白屏尴尬!
Ⅰ、前言 当我们每次打卡页面,切换路由,甚至于异步组件,都会有一个等待的时间 ;为了不白屏,提高用户体验,添加一个 loading 过度动画是 非常 常见的 ;那么这几种场景我们应该把 loading 加在哪…...
基于sringboot和小程序实现高校食堂移动预约点餐系统演示【源码】
基于sringboot实现高校食堂移动预约点餐系统演示开发语言:Java 框架:ssm JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件&am…...
开源操作系统与Windows大比拼!
科技网站ZDNet近日撰文称,在一个用户为王的时代,操作系统们为了获得青睐都放下了身段,采用免费策略,但其中却有一个例外——Windows 10。这样的一反常理让许多人不看好Windows的未来,难道这个我们最熟悉的朋友真的会成…...
RK3588开发板USB转CAN踩坑实录:CH341成功驱动与PCAN内核编译全流程
RK3588开发板USB转CAN实战指南:CH341与PCAN驱动深度解析 当工业控制、车载电子或机器人系统需要扩展CAN总线接口时,RK3588开发板配合USB转CAN模块成为工程师的热门选择。本文将深入探讨两种经过验证的解决方案——CH341转CAN和PCAN模块,从硬件…...
暗黑2终极增强:PlugY插件如何彻底改变你的单机游戏体验
暗黑2终极增强:PlugY插件如何彻底改变你的单机游戏体验 【免费下载链接】PlugY PlugY, The Survival Kit - Plug-in for Diablo II Lord of Destruction 项目地址: https://gitcode.com/gh_mirrors/pl/PlugY 还在为暗黑破坏神2单机模式的种种限制而烦恼吗&am…...
为什么头部AI团队已弃用Triton+ONNX Runtime?Cuvil架构设计图暴露Python推理第三条路!
第一章:Cuvil编译器在Python AI推理中的应用全景概览Cuvil编译器是一款面向AI工作负载的轻量级领域专用编译器,专为优化Python生态中基于PyTorch、ONNX及自定义计算图的推理流程而设计。它不替代传统Python解释器,而是通过源码到IR࿰…...
【RT-DETR涨点改进】TGRS 2026 | 全网独家创新、特征融合改进篇| 引入STSAM协同时空注意力融合模块,发论文热点创新,注意力能够互相引导强化边界和结构细节,增强目标检测高效涨点
一、本文介绍 🔥本文给大家介绍使用 STSAM协同时空注意力融合模块 改进RT-DETR网络模型,STSAM 是 空间域特征增强模块,通过全局跨时相注意力和局部坐标注意力的并行处理,能有效聚焦真实变化目标,强化边界和结构细节,同时兼顾训练稳定性,为后续浅层特征融合提供高质量特…...
OpenClaw自动化测试:Qwen3.5-9B-AWQ-4bit驱动UI截图比对
OpenClaw自动化测试:Qwen3.5-9B-AWQ-4bit驱动UI截图比对 1. 为什么需要自动化UI测试 作为个人开发者,每次前端代码修改后最头疼的就是手动检查各个页面的UI变化。传统做法要么是人工逐页比对,要么依赖复杂的测试框架配置。直到我发现OpenCl…...
你还在用for循环清洗CSV?Polars 2.0的scan_csv()+expression DSL已支持自动列式推断与零拷贝转换——立即升级避免被淘汰
第一章:Polars 2.0大规模数据清洗的核心范式变革Polars 2.0 不再将数据清洗视为一系列离散的、命令式的转换操作,而是以“惰性执行图列式语义优先”为基石,重构整个清洗生命周期。其核心变革体现在计算模型、内存管理与API设计三重维度的协同…...
视频SEO软件对网站流量有什么影响
视频SEO软件对网站流量有什么影响 在当今数字化时代,网站流量的获取和管理是每一个网站运营者关注的重点。而视频SEO软件作为一种现代化的工具,在提升网站流量方面扮演着重要角色。视频SEO软件究竟对网站流量有什么影响呢?我们将从问题分析、…...
热门AI命理工具盘点:星座、运势、排盘工具一次看
很多朋友对传统命理文化感兴趣,却怕找不对专业靠谱的工具,今天我们就整理了10款不同方向的AI命理相关工具,涵盖星座、面相、运势测算、专业排盘等不同需求,大家可以按需选择。 一、专业命理首选:天府 Agent 链接&#…...
杭州污水提升泵靠谱厂家
在杭州及周边地区进行地下室改造、商业空间建设或解决特殊排污需求时,选择一家技术可靠、服务专业的污水提升泵厂家至关重要。在众多厂家中,杭州富阳赛特仪表阀门有限公司(赛斯瑞特) 凭借其深厚的技术积淀、过硬的产品品质和完善的…...
线性结构之链表[基于郝斌课程]
每个结点只有一个前续结点每个结点只有一个后续结点首结点没有前续结点尾结点没有后续结点专业术语:首结点:第一个有效结点,存放第一个有效数据尾结点:最后一个有效结点,存放最后一个有效数据头结点:在首结…...
