重庆首页设计公司/搜索引擎优化的工具
本篇文章主要是实现一个简易的通讯录:
功能如下:
- 添加用户
- 修改用户
- 删除用户
- 查找用户(可重名)
- 按名字或年龄排序
- 显示用户
- 保存通讯录
- 日志追加
有如下知识点:
- 动态数组
- 结构体
- 枚举
- 自定义标识符和宏
- 文件打开与存储
- 函数
- 指针
- 循环
- 排序
简述特点:
- 将人员信息放在一个PeoInf的结构体中,再创建一个结构体List,用于存放peoinf这个结构体的指针,和容量与目前通讯录人员数量。
- 再用realloc动态开辟以结构体peoinf为大小的内存,用于实现动态内存开辟。
- 程序运行后,初始化这段空间,并查询是否有“contact.txt”的文件存在,如果存在,则读取文件里的内容,并放到peoinf的结构体“数组”中,并实时监控是否需要扩容。如果不存在就创建文件。
- 随后就可以添加、修改、查找、删除用户,每一次增删改查都会被记录到一个“contact_log.txt”的文件里,这里使用了时间戳。
- 用qsort进行名字或年龄进行排序
- 程序会知道本次是否进行修改,如果修改后就退出会提示是否需要保存,当然也可以自己手动保存。
- 程序以“rb”和“wb”进行文件的读写。
- 程序实现了重名查找,在有重名的情况下会进行选择。
- (代码可直接运行,复制到编译器vs2019即可)
代码部分
-
contact.h
#pragma once #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <assert.h> #include <time.h> #include <sys/stat.h>#define MAX_10 10 #define MAX_20 20 //#define LOG_PRINT(x) fprintf(pf, "In %s %s ,user %s name calling %s\n",__DATE__,__TIME__,(x),(list->pl+num)->name) typedef struct PeoInf {char name[MAX_20];int age;char sex[5];char tel[12];char addr[30]; }PeoInf; //定义通讯录结构体,嵌套PeoInf typedef struct List {//动态内存分配PeoInf* pl;int count;int capacity;//容量 }List; //定义一个枚举变量,用于存储菜单所有选择 enum select_all {EXIT,//0ADD,DEL,SELECT,MODIFY,SORT,SHOW,SAVE }; //菜单函数 void menu(); //定义初始化list函数 void initialise_list(List* list); //定义添加信息函数 void add_peoinf(List* list); //定义显示函数 void show_list(List* list); //定义删除函数 void del_peoinf(List* list); //定义通过找名字查找人的函数(已实现重名查找) int find_byname(const List* list); //定义查找人 void sele_peoinf(const List* list); //定义修改人信息函数 void modify_peoinf(List* list); //定义删除和修改已找到下标的信息函数 void del_havefond(List* list, int position); void modify_havefond(List* list, int position); //定义排序函数 void sort_peoinf(List* list); //定义文件保存函数 void file_save(List* list); //定义扩容函数 void expand_list(List* list);
-
actualize.c
#include "contact.h" //实现菜单函数 void menu(){printf("----------------------------------------\n");printf("--------1. add 2. del--------------\n");printf("--------3. select 4. modify-----------\n");printf("--------5. sort 6. show-------------\n");printf("--------------7. save-------------------\n");printf("--------------0. exit-------------------\n");printf("----------------------------------------\n"); } //实现初始化list函数 void initialise_list(List* list){PeoInf* ptr = (PeoInf*)calloc(3, sizeof(PeoInf));//默认开辟三个人的存储空间if (ptr == NULL) {printf("%s", strerror(errno));return ;}list->pl = ptr;list->count = 0;list->capacity = 3;FILE* pf = NULL;struct stat buffer;//判断文件是否存在if (stat("contact.txt", &buffer) != 0) {//不存在就创建文件pf = fopen("contact.txt", "wb");fclose(pf);pf = NULL;return;}pf = fopen("contact.txt", "rb");if (pf != NULL) {for (int i = 0; fread(list->pl + i, sizeof(PeoInf), 1, pf) != 0; i++) {if (list->count == list->capacity - 1) {expand_list(list);}list->count++;}fclose(pf);}pf = NULL; } //扩容函数 void expand_list(List* list) {PeoInf* ptr =(PeoInf*) realloc(list->pl, (list->capacity + 2)*sizeof(PeoInf));//每次增加两个if (ptr == NULL) {printf("%s", strerror(errno));return;}list->pl = ptr;list->capacity += 2; } //实现添加日志功能 /* * return 0 失败 * return 1 成功 */ int add_log(List* list,char* moving,int num) {//打开文件FILE* pf=NULL;//判断写入模式是否要追加if (list->count == 0) {pf = fopen("contact_log.txt", "w");}else {pf = fopen("contact_log.txt", "a");}//如果打开失败,报错if (pf == NULL) {perror("fopen:");return 0;}//获取时间戳time_t rawtime;struct tm* timeinfo;time(&rawtime);timeinfo = localtime(&rawtime);fprintf(pf, "In %s \tuser %s name calling %s.\n", asctime(timeinfo), moving, (list->pl + num)->name);fclose(pf);pf = NULL;return 1; } //实现添加信息功能 void add_peoinf(List* list) {assert(list);//断言//判断是否需要扩容if (list->count == list->capacity) {expand_list(list);//内部函数,不必去头文件里定义printf("Automatic capacity expansion is successful,\n and the current address book capacity is %d\n", list->capacity);}printf("Please enter the name\n->");scanf("%s", (list->pl+list->count)->name);printf("Please enter age\n->");scanf("%d", &(list->pl + list->count)->age);printf("Please enter sex\n->");scanf("%s", (list->pl + list->count)->sex);printf("Please enter the telephone\n->");scanf("%s", (list->pl + list->count)->tel);printf("Please enter the address\n->");scanf("%s", (list->pl + list->count)->addr);//添加日志log功能if (!add_log(list,"add",list->count)) {printf("log fail,please find excause.\n");}list->count++;printf("succeed!\n"); } //实现显示函数 void show_list(List* list) {assert(list);printf("name\tage\tsex\ttelephone\taddr\n");for (int i = 0; i < (list->count); i++) {printf("%s\t%d\t%s\t%s\t\t%s\n", (list->pl + i)->name,(list->pl + i)->age, (list->pl + i)->sex, (list->pl + i)->tel, (list->pl + i)->addr);} } //实现通过寻找名字,找到这个人 //重名默认存放数组为10,如需变大可改为动态扩容实现 int find_byname(const List* list) {char s_name[MAX_20] = { 0 };int count = 0;int find_result[MAX_10] = { 0 };printf("Please enter the name that you want \n->");scanf("%s", s_name);for (int i = 0; i < list->count; i++) {if (strcmp((list->pl + i)->name, s_name)==0) {//找到了if (count == 0) {printf("Find the information, please confirm\n");printf("number\tname\tage\tsex\ttelephone\taddr\n");}printf("%d\t%s\t%d\t%s\t%s\t\t%s\n", count+1,(list->pl + i)->name,(list->pl + i)->age, (list->pl + i)->sex, (list->pl + i)->tel, (list->pl + i)->addr);find_result[count] = i;//将找到的坐标存入数组中count++;//判断是否有重复}}if (count == 0) {//找不到printf("Check no such person, please confirm after the input!\n");return -1;}else if (count == 1) {return find_result[0];}else {//两个以上int select_num = 0;while (1) {printf("Please select the object serial number that you want to operate on\n->");scanf("%d", &select_num);if (select_num >= 1 && select_num <= count) {//输入正确序号,方可返回return find_result[select_num - 1];}else {printf("error,please reenter\n");}}} } //实现删除函数 void del_peoinf(List* list) {assert(list);int del_num = find_byname(list);if (del_num < 0) return;//查找失败for (int i = 0; i < list->count - del_num - 1; i++) {*(list->pl + del_num + i) = *(list->pl + del_num + 1 + i);}list->count--;printf("delet successfully\n");if (!add_log(list, "delet", del_num)) {printf("log fail,please find excause.\n");} } void del_havefond(List* list,int position) {assert(list);for (int i = 0; i < list->count - position - 1; i++) {*(list->pl + position + i) = *(list->pl + position + 1 + i);}list->count--;printf("delet successfully\n");if (!add_log(list, "delet", position)) {printf("log fail,please find excause.\n");} } //实现查找信息功能 void sele_peoinf(const List* list) {assert(list);int find_num = find_byname(list);if (find_num < 0) return;//查找失败printf("The information is as follows\n");printf("name\tage\tsex\ttelephone\taddr\n");printf("%s\t%d\t%s\t%s\t\t%s\n", (list->pl + find_num)->name,(list->pl + find_num)->age, (list->pl + find_num)->sex, (list->pl + find_num)->tel, (list->pl + find_num)->addr);int input_find = 0;do {printf("--------------------------------\n");printf("--------------------------------\n");printf("-----1. del-------2. modif------\n");printf("------------0. exit-------------\n");printf("--------------------------------\n");printf("--------------------------------\n");printf("please enter what you want\n->");scanf("%d", &input_find);if (input_find == 1) {del_havefond(list, find_num);return;}else if (input_find == 2) {modify_havefond(list, find_num);return;}else if (input_find != 0) {printf("Input is wrong, please reagain\n");}} while (input_find);} void modify_havefond(List* list,int position) {assert(list);printf("Please enter the new name\n->");scanf("%s", (list->pl + position)->name);printf("Please enter new age\n->");scanf("%d", &(list->pl + position)->age);printf("Please enter new sex\n->");scanf("%s", (list->pl + position)->sex);printf("Please enter the new telephone\n->");scanf("%s", (list->pl + position)->tel);printf("Please enter the new address\n->");scanf("%s", (list->pl + position)->addr);printf("Modified successfully\n");if (!add_log(list, "modify", position)) {printf("log fail,please find excause.\n");} } //实现修改信息 void modify_peoinf(List* list) {assert(list);int mod_num = find_byname(list);if (mod_num < 0) return;//查找失败printf("Please enter the new name\n->");scanf("%s", (list->pl + mod_num)->name);printf("Please enter new age\n->");scanf("%d", &(list->pl + mod_num)->age);printf("Please enter new sex\n->");scanf("%s", (list->pl + mod_num)->sex);printf("Please enter the new telephone\n->");scanf("%s", (list->pl + mod_num)->tel);printf("Please enter the new address\n->");scanf("%s", (list->pl + mod_num)->addr);printf("Modified successfully\n");if (!add_log(list, "modify",mod_num)) {printf("log fail,please find excause.\n");} } //qsort的比较函数 int compare_name(const void* e1,const void* e2) {return strcmp(((PeoInf*)e1)->name, ((PeoInf*)e2)->name);} int compare_age(const void* e1, const void* e2) {return ((PeoInf*)e1)->age - ((PeoInf*)e2)->age;} //实现排序函数 void sort_peoinf(List* list) {int sort_input = 0;do {printf("--------------------------------\n");printf("--------------------------------\n");printf("-----1. name-------2. age------\n");printf("------------0. exit-------------\n");printf("--------------------------------\n");printf("--------------------------------\n");printf("please enter you want sort by\n->");scanf("%d", &sort_input);if (sort_input == 1) {qsort(list->pl, list->count, sizeof(PeoInf), compare_name);printf("sort by name successfully\n");return;}else if (sort_input == 2) {qsort(list->pl, list->count, sizeof(PeoInf), compare_age);printf("sort by age successfully\n");return;}} while (sort_input);} void file_save(List *list) {FILE* pf = fopen("contact.txt", "wb");//二进制写入if (pf == NULL) {perror("fopen:");return;}//写数据for (int i = 0; i < list->count; i++) {fwrite(list->pl+i, sizeof(PeoInf), 1, pf);}fclose(pf);pf = NULL; }
-
test.c
#include "contact.h" int main() {int input = 0;List list;initialise_list(&list);//动态内存开辟,记得用完销毁int modify_num = 0;//修改数量记录do{menu();printf("Please choose!\n->");scanf("%d", &input);switch (input){case ADD: {add_peoinf(&list);modify_num++;}break;case DEL:{del_peoinf(&list);modify_num++;}break;case SELECT:{sele_peoinf(&list);}break;case MODIFY:{modify_peoinf(&list);modify_num++;}break;case SORT:{sort_peoinf(&list);}break;case SHOW:{show_list(&list);}break;case SAVE:{file_save(&list);printf("save in file sucessfully\n");modify_num = 0;}break;case EXIT:{if (modify_num != 0) {int save_select = 0;printf("=========1.save 2.no=============\n");printf("The modified data is not saved, whether it needs to be saved\n->");scanf("%d", &save_select);if (save_select == 1) {file_save(&list);printf("save in file sucessfully\n");}}printf("Ok,have a nice day! Bye~");}break;default:printf("Input is wrong,please reagain!\n");break;}} while (input);//销毁动态内存free(list.pl);list.pl = NULL; }
希望对大家有帮助!
相关文章:

C语言程序设计—通讯录实现
本篇文章主要是实现一个简易的通讯录: 功能如下: 添加用户修改用户删除用户查找用户(可重名)按名字或年龄排序显示用户保存通讯录日志追加 有如下知识点: 动态数组结构体枚举自定义标识符和宏文件打开与存储函数指针…...

实战:大数据Flink CDC同步Mysql数据到ElasticSearch
文章目录 前言知识积累CDC简介CDC的种类常见的CDC方案比较 Springboot接入Flink CDC环境准备项目搭建 本地运行集群运行将项目打包将包传入集群启动远程将包部署到flink集群 写在最后 前言 前面的博文我们分享了大数据分布式流处理计算框架Flink和其基础环境的搭建,…...

B-Tree 索引和 Hash 索引的对比
分析&回答 B-Tree 索引的特点 B-tree 索引可以用于使用 , >, >, <, < 或者 BETWEEN 运算符的列比较。如果 LIKE 的参数是一个没有以通配符起始的常量字符串的话也可以使用这种索引。 有时,即使有索引可以使用,MySQL 也不使用任何索引。…...

入门Python编程:了解计算机语言、Python介绍和开发环境搭建
文章目录 Python入门什么是计算机语言1. 机器语言2. 符号语言(汇编)3. 高级语言 编译型语言和解释型语言1. 编译型语言2. 解释型语言 Python的介绍Python开发环境搭建Python的交互界面 python学习专栏python基础知识(0基础入门)py…...

深度解析Redisson框架的分布式锁运行原理与高级知识点
推荐阅读 项目实战:AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间 资源分享 史上最全文档AI绘画stablediffusion资料分享 AI绘画关于SD,MJ,GPT,SDXL百科全书 AI绘画 stable…...

C#扩展方法
参数列表中this的这种用法是在.NET 3.0之后新增的一种特性---扩展方法。通过这个属性可以让程序员在现有的类型上添加扩展方法(无需创建新的派生类型、重新编译或者以其他方式修改原始类型)。 扩展方法是一种特殊的静态方法,虽然是静态方法&a…...

uniapp 高度铺满全屏
问题:在有uni-tabbar的情况下,页面铺满剩下的部分 <template><view :style"{height:screenHeightpx}" class"page"></view> </template> <script>export default {data() {return {screenHeight: &q…...

UG\NX二次开发 判断向量在指定的公差内是否为零,判断是否是零向量 UF_VEC3_is_zero
文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 简介: UG\NX二次开发 判断向量在指定的公差内是否为零,判断是否是零向量 UF_VEC3_is_zero 效果: 代码: #include "me.hpp"void ufusr(char* param, int* retco…...

2023年MySQL实战核心技术第一篇
目录 四 . 基础架构:一条SQl查询语句是如何执行的? 4.1 MySQL逻辑架构图: 4.2 MySQL的Server层和存储引擎层 4.2.1 连接器 4.2.1.1 解释 4.2.1.2 MySQL 异常重启 解决方案: 4.2.1.2.1. 定期断开长连接: 4.2.1.2.2. 初始…...

hivesql执行过程
语法解析 SemanticAnalyzer SemanticAnalyzer是Hive中的语义分析器,负责检查Hive SQL程序的语义是否正确。SemanticAnalyzer会对Hive SQL程序进行以下检查: 检查过程 语法检查 SemanticAnalyzer会检查Hive SQL程序的语法是否正确,包括关…...

C语言学习:8、深入数据类型
数据超过类型规定的大小怎么办 C语言中,如果需要用的整数大于int类型的最大值了怎么办? 我们知道int能表示的最大数是2147483647,最小的数是-2147483648,为什么? 因为字32位系统中,寄存器是32位的&#…...

生成树协议 STP(spanning-tree protocol)
一、STP作用 1、消除环路:通过阻断冗余链路来消除网络中可能存在的环路。 2、链路备份:当活动路径发生故障时,激活备份链路,及时恢复网络连通性。 二、STP选举机制 1、目的:找到阻塞的端口 2、STP交换机的角色&am…...

【LeetCode】312.戳气球
题目 有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。 现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i 1] 枚硬币。 这里的 i - 1 和 i 1 代表和…...

商业数据分析概论
🐳 我正在和鲸社区参加“商业数据分析训练营活动” https://www.heywhale.com/home/competition/6487de6649463ee38dbaf58b ,以下是我的学习笔记: 学习主题:波士顿房价数据快速查看 日期:2023.9.4 关键概念/知识点&…...

Golang GUI框架
Golang GUI框架fyne fyne简介第一个fyne应用fyne应用程序和运行循环fyne更新GUI内容fyne窗口处理fyne解决中文乱码问题fyne应用打包fyne画布和画布对象fyne容器和布局fyne绘制和动画fyne盒子布局fyne网格grid布局fyne网格包裹布局fyne边框布局fyne表单布局fyne中心布局fyne ma…...

LeetCode刷题笔记【24】:贪心算法专题-2(买卖股票的最佳时机II、跳跃游戏、跳跃游戏II)
文章目录 前置知识122.买卖股票的最佳时机II题目描述贪心-直观写法贪心-优化代码更简洁 55. 跳跃游戏题目描述贪心-借助ability数组贪心-只用int far记录最远距离 45.跳跃游戏II题目描述回溯算法贪心算法 总结 前置知识 参考前文 参考文章: LeetCode刷题笔记【23】…...

游戏出现卡顿有哪些因素
一、服务器CPU内存占用过大会导致卡顿,升级CPU内存或者优化自身程序占用都可以解决。 二、带宽跑满导致卡,可以升级带宽解决。 二、平常不卡,有大型的活动的时候会卡,这方面主要是服务器性能方面不够导致的,性能常说…...

学习Bootstrap 5的第八天
目录 加载器 彩色加载器 实例 闪烁加载器 实例 加载器大小 实例 加载器按钮 实例 分页 分页的基本结构 实例 活动状态 实例 禁用状态 实例 分页大小 实例 分页对齐 实例 面包屑(Breadcrumbs) 实例 加载器 彩色加载器 在 Bootstr…...

vue中自定义指令
什么是指令 在Vue.js中,指令是一种特殊的 token,用于在模板中以声明式方式将响应式数据绑定到 DOM 元素上,从而实现与 DOM 元素的交互和操作。指令以 “v-” 前缀开始,后跟指令的名称,例如 v-model、v-bind 和 v-on。…...

Python:安装Flask web框架hello world
安装easy_install pip install distribute 安装pip easy_install pip 安装 virtualenv pip install virtualenv 激活Flask pip install Flask 创建web页面demo.py from flask import Flask app Flask(__name__)app.route(/) def hello_world():return Hello World! 2023if _…...

小程序点击复制功能制作
在wxml文件中添加一个按钮或需要点击的元素,并绑定点击事件监听器2 <button bindtap"copyText">点击复制</button> 2 在对应的js文件中定义点击事件处理函数,并在函数中调用小程序的API进行复制操作, copyText(e){co…...

20230909java面经整理
1.java常用集合 ArrayList动态数组,动态调整大小,实现List接口 LinkedList双向链表,实现list和queue接口,适用于频繁插入和删除操作 HashSet无序,使用哈希表实现 TreeSet有序,使用红黑树实现 HashMap无序&…...

常用的css命名规则
一、命名规则说明: 1)、所有的命名最好都小写 2)、属性的值一定要用双引号(“”)括起来 3)、给图片加上alt标签 4)、尽量使用英文命名原则 5)、尽量不缩写,除非一看就明白的单词 二、相对网页外…...

【Linux编程Shell自动化脚本】03 shell四剑客(find、sed、grep、awk)
文章目录 一、find1. 常用expression2. 时间参数3. 其他选项参数3.1 查找深度3.2 执行命令 二、sed1. 常用命令选项2. 常用动作脚本命令2.1 s 替换2.2 已匹配字符串标记&2.3 在当前行前后插入文本 a\ 和 i\2.4 p 打印指定行2.5 匹配行的方式2.5.1 以数字形式指定行区间2.5.…...

java的springboot框架中使用logback日志框架使用RabbitHandler注解为什么获取不到消费的traceId信息?
当使用 Logback 日志框架和 RabbitMQ 的 RabbitHandler 注解时,如果无法获取消费的 traceId 信息,可能是因为在处理 RabbitMQ 消息时,没有正确地将 traceId 传递到日志中。 为了将 traceId 传递到日志中,你可以利用 MDCÿ…...

初探Vue.js及Vue-Cli
一、使用vue框架的简单示例 我们本次的vue系列就使用webstorm来演示: 对于vue.js的安装我们直接使用script的cdn链接来实现 具体可以参考如下网址: https://www.bootcdn.cn/ 进入vue部分,可以筛选版本,我这里使用的是2.7.10版本的ÿ…...

大数据课程K21——Spark的SparkSQL基础语法
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Spark的SparkSQL通过方法来使用; ⚪ 掌握Spark的SparkSQL通过sql语句来调用; 一、SparkSQL基础语法——通过方法来使用 1. 查询 df.select("id","name").show()…...

【实践篇】Redis最强Java客户端(三)之Redisson 7种分布式锁使用指南
文章目录 0. 前言1. Redisson 7种分布式锁使用指南1.1 简单锁:1.2 公平锁:1.3 可重入锁:1.4 红锁:1.5 读写锁:1.6 信号量:1.7 闭锁: 2. Spring boot 集成Redisson 验证分布式锁3. 参考资料4. 源…...

卫星通话过后,卫星导航产业被彻底激活
华为新手机发布后,其主打的卫星通话功能备受热议。在卫星产业链发展的背后,下一个大产业在哪里让人颇为好奇。 目前,卫星导航颇被看好,或将引领下一个技术狂潮。它的特点是产业大、发展快、参与者多。继电动汽车、新能源和芯片产…...

【算法训练-链表 七】【排序】:链表排序、链表的奇偶重排、重排链表
废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【链表的排序】,使用【链表】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为&am…...