【C语言练习】DOS黑框框通讯录(使用结构体、动态内存管理联系人信息,函数指针等)

文章目录

  • 1. contacts.h 头文件、函数/常量/结构体声明
  • 2. test.c 主界面菜单打印、菜单功能选项选择
  • 3. contacts.c 函数实现
  • 4. 使用结构体、动态内存,函数指针实现时的注意点
  • 5. 运行演示

1. contacts.h 头文件、函数/常量/结构体声明

#pragma once#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>// 姓名和地址长度
#define NAME_LEN 20
#define ADDR_LEN 40// 通讯录大小(能存储多少个联系人)
#define CONTACTS_SIZE 1000/* 联系人信息:姓名、性别、年龄、电话、住址。 */
typedef struct PeopleInfo
{char* name;char gender;short age;char tele[11];char* addr;
} PeopleInfo;/* 通讯录信息 */
typedef struct Contacts
{PeopleInfo* peopleInfo;int peopleNums;
} Contacts;// 初始化通讯录
void InitContacts(Contacts* contacts);// 添加联系人
void AddContacts(Contacts* contacts);// 查找联系人
int SearchContactsByName(Contacts* contacts);// 显示所有联系人
void ShowAllContacts(Contacts* contacts);// 修改联系人
void ModifyByName(Contacts* contacts);// 删除联系人
void DeleteContacts(Contacts* contacts);// 对所有联系人按照某种方式排序
void SortContacts(Contacts* contacts);

2. test.c 主界面菜单打印、菜单功能选项选择

#define _CRT_SECURE_NO_WARNINGS 1/**(1)实现一个通讯录;通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址*(2)提供方法:1.添加联系人信息2.删除指定联系人信息3.查找指定联系人信息4.修改指定联系人信息5.显示所有联系人信息6.清空所有联系人7.以名字排序所有联系人
*/#include "contacts.h"// static修饰,不将该函数暴露在外部
static void menu()
{printf("\n----- OPTIONS ----- OPTIONS ----- OPTIONS -----\n");printf(" ************** 1.ADD ********************* \n");printf(" ************** 2.DELETE ****************** \n");printf(" ************** 3.SEARCH ****************** \n");printf(" ************** 4.MODIFY ****************** \n");printf(" ************** 5.SHOW ALL **************** \n");printf(" ************** 6.DELETE ALL ************** \n");printf(" ************** 7.SORT ******************** \n");printf(" ************** 0.EXIT ******************** \n");printf("----- OPTIONS ----- OPTIONS ----- OPTIONS -----\n\n");
}/* 菜单选项作为枚举常量表示 */
enum Option
{EXIT,ADD,DELETE,SEARCH,MODIFY,SHOW_ALL,DELETE_ALL,SORT
};int main()
{/* 初始化通讯录 */Contacts contacts;InitContacts(&contacts);short input = 0;do {menu();printf("请选择:");scanf("%hd", &input);getchar();/* 根据选项执行相应操作 */switch (input){case ADD:printf("\nADD.\n");AddContacts(&contacts);break;case DELETE:printf("\nDELETE.\n");DeleteContacts(&contacts);break;case SEARCH:printf("SEARCH.\n");printf("Who do you want to search?\n");int index = SearchContactsByName(&contacts);if (index < 0){printf("The contacts you just searched doesn't exist in your contacts.\n\n");}else {printf("SEARCH SUCCEED!\n");printf("| %-20s | %s | %s | %-11s | %-40s |\n","NAME", "GENDER", "AGE", " TELEPHONE ", "ADDRESS");printf("------------------------------------------------------------------------------------------------\n");printf("| %-20s | %3c    | %2hd  | %-11s | %-40s |\n\n",(contacts.peopleInfo + index)->name,(contacts.peopleInfo + index)->gender,(contacts.peopleInfo + index)->age,(contacts.peopleInfo + index)->tele,(contacts.peopleInfo + index)->addr);}break;case MODIFY:printf("\nMODIFY.\n");ModifyByName(&contacts);break;case SHOW_ALL:printf("\nSHOW ALL CONTACTS.\n");ShowAllContacts(&contacts);break;case DELETE_ALL:printf("\nDELETE ALL CONTACTS.\n");// 后续添加都会从0下标处开始contacts.peopleNums = 0;printf("DELETE ALL CONTACTS SUCCEED!\n\n");break;case SORT:printf("\nSORT.\n");SortContacts(&contacts);break;case EXIT:printf("\nEXIT.\n");break;default:printf("\nWRONG OPERATION.\n");break;}} while (input);/* 释放通讯录数据 */free(contacts.peopleInfo);contacts.peopleInfo = NULL;return 0;
}

3. contacts.c 函数实现

#define _CRT_SECURE_NO_WARNINGS 1#include "contacts.h"/* getchar()目的为了把输入缓冲区的换行字符清空 *//* 初始化通讯录(以动态内存方式) */
void InitContacts(Contacts* contacts)
{/* calloc会把成员变量的值初始化为0(如果成员为指针变量则指向NULL) */contacts->peopleInfo = (PeopleInfo*)calloc(CONTACTS_SIZE, sizeof(PeopleInfo));contacts->peopleNums = 0;/** 由于指针变量成员指向NULL,必须要为指针变量(每一个联系人的姓名、地址)申请一块内存,* 这样的话calloc会将内存分配后,给指针变量指向一个空串(内容仅仅只有\0的串)。*/for (int i = 0; i < CONTACTS_SIZE; i++) {(contacts->peopleInfo + i)->name = (char*)calloc(NAME_LEN, sizeof(char));(contacts->peopleInfo + i)->addr = (char*)calloc(ADDR_LEN, sizeof(char));}
}/* 添加联系人 */
void AddContacts(Contacts* contacts)
{assert(contacts);int size = contacts->peopleNums;PeopleInfo* peopleInfo = contacts->peopleInfo + size;printf("NAME:");scanf("%[^\n]s", peopleInfo->name);getchar();printf("GENDER:");scanf("%c", &(peopleInfo->gender));getchar();printf("AGE:");scanf("%hd", &(peopleInfo->age));getchar();printf("TELEPHONE:");scanf("%s", peopleInfo->tele);getchar();printf("ADDRESS:");scanf("%[^\n]s", peopleInfo->addr);getchar();(contacts->peopleNums)++;printf("\nADD SUCCEED!\n");
}/** 查找联系人* @返回值:如果不存在返回-1,找到返回下标。
*/
int SearchContactsByName(Contacts* contacts)
{char name[NAME_LEN];printf("\nPlease enter the contacts' name:");scanf("%[^\n]s", name);getchar();for (int i = 0; i < contacts->peopleNums; i++){if (strcmp(name, contacts->peopleInfo->name) == 0){return i;}}return -1;
}/* 显示所有联系人 */
void ShowAllContacts(Contacts* contacts)
{printf("| %-20s | %s | %s | %-11s | %-40s |\n","NAME", "GENDER", "AGE", " TELEPHONE ", "ADDRESS");printf("-----------------------------------------------------------------------------------------------------\n");for (int i = 0; i < contacts->peopleNums; i++){printf("| %-20s | %3c    | %2hd  | %-11s | %-40s |\n",(contacts->peopleInfo + i)->name,(contacts->peopleInfo + i)->gender,(contacts->peopleInfo + i)->age,(contacts->peopleInfo + i)->tele,(contacts->peopleInfo + i)->addr);}
}/* 修改联系人 */
void ModifyByName(Contacts* contacts)
{if (contacts->peopleNums <= 0){printf("No contacts in your contacts book.\n\n");return;}assert(contacts->peopleInfo);printf("\nWhose information you want to modify?\n");int index = SearchContactsByName(contacts);if (index < 0){printf("\nCannot find the information.\n\n");return;}PeopleInfo* peopleInfo = contacts->peopleInfo + index;printf("\nORIGINAL INFORMATION:\n");printf("| %-20s | %s | %s | %-11s | %-40s |\n","NAME", "GENDER", "AGE", " TELEPHONE ", "ADDRESS");printf("------------------------------------------------------------------------------------------------\n");printf("| %-20s | %3c    | %2hd  | %-11s | %-40s |\n\n",peopleInfo->name,peopleInfo->gender,peopleInfo->age,peopleInfo->tele,peopleInfo->addr);/* 选择修改指定信息 */printf("----- MODIFICATION OPTIONS ----- \n");printf(" *********** 1.NAME *********** \n");printf(" *********** 2.GENDER *********** \n");printf(" *********** 3.AGE *********** \n");printf(" *********** 4.TELEPHONE *********** \n");printf(" *********** 5.ADDRESS *********** \n");printf(" *********** 0.EXIT MODIFICATION *********** \n");printf("----- MODIFICATION OPTIONS ----- \n\n");short input;do{printf("What information you want to modify?:");scanf("%hd", &input);getchar();switch (input){case 0:printf("\nEXIT MODIFICATION.\n");break;case 1:printf("\nMODIFY NAME:");scanf("%[^\n]s", peopleInfo->name);getchar();break;case 2:printf("\nMODIFY GENDER:");scanf("%c", &(peopleInfo->gender));getchar();break;case 3:printf("\nMODIFY AGE:");scanf("%hd", &(peopleInfo->age));getchar();break;case 4:printf("\nMODIFY TELEPHONE:");scanf("%s", peopleInfo->tele);getchar();break;case 5:printf("\nMODIFY ADDRESS:");scanf("%[^\n]s", peopleInfo->addr);getchar();break;default:printf("\nWRONG OPERATION.\n");break;}} while (input);printf("\nMODIFIED INFORMATION:\n");printf("| %-20s | %s | %s | %-11s | %-40s |\n","NAME", "GENDER", "AGE", " TELEPHONE ", "ADDRESS");printf("------------------------------------------------------------------------------------------------\n");printf("| %-20s | %3c    | %2hd  | %-11s | %-40s |\n\n",peopleInfo->name,peopleInfo->gender,peopleInfo->age,peopleInfo->tele,peopleInfo->addr);printf("\nMODIFY SUCCEED!\n");
}/* 删除联系人 */
void DeleteContacts(Contacts* contacts)
{if (contacts->peopleNums <= 0){printf("You don't have any contacts.\n\n");return;}assert(contacts->peopleInfo);ShowAllContacts(contacts);printf("\nWho do you want to delete?\n");int index = SearchContactsByName(contacts);if (index < 0){printf("\nThe contacts you just searched doesn't exist in your contacts.\n\n");return;}PeopleInfo* peopleInfo = contacts->peopleInfo;for (int i = index; i < contacts->peopleNums - 1; i++){	// 只要成员一样,结构体可以直接赋值另一个结构体*(peopleInfo + i) = *(peopleInfo + i + 1);}contacts->peopleNums--;printf("\nDELETE SUCCEED!\n\n");
}/* 根据年龄升序排序 */
static int CmpByAge(PeopleInfo* p1, PeopleInfo* p2)
{return p1->age - p2->age;
}
/* 根据姓名中的字母升序排序 */
static int CmpByName(PeopleInfo* p1, PeopleInfo* p2)
{return strcmp(p1->name, p2->name);
}
/* 对联系人排序 */
static void SortPeopleInfo(Contacts* contacts, int (*pfCmp)(PeopleInfo*, PeopleInfo*))
{PeopleInfo* peopleInfo = contacts->peopleInfo;int size = contacts->peopleNums;int sortedBorder = size - 1;int lastExchange = 0;for (int i = 0; i < size - 1; i++){bool flg = true;for (int j = 0; j < sortedBorder; j++){if (pfCmp(peopleInfo + j, peopleInfo + j + 1) > 0){flg = false;PeopleInfo tmp = *(peopleInfo + j);*(peopleInfo + j) = *(peopleInfo + j + 1);*(peopleInfo + j + 1) = tmp;lastExchange = j;}}if (flg){break;}sortedBorder = lastExchange;}
}
/* 按照选择的方式排序 */
void SortContacts(Contacts* contacts)
{printf("Sorting by what?Please Choose:\n");printf("********** 1. the age.\n");printf("********** 2. the name.\n\n");short input;scanf("%hd", &input);switch (input){case 1:printf("Sorting by age...\n\n");SortPeopleInfo(contacts, CmpByAge);break;case 2:printf("Sorting by name...\n\n");SortPeopleInfo(contacts, CmpByName);break;default:printf("\nWRONG CHOICE.\n");break;}printf("The contacts information after sorting:\n\n");ShowAllContacts(contacts);
}

4. 使用结构体、动态内存,函数指针实现时的注意点

  1. 初始化在这里插入图片描述
  2. 避免后续使用时参数太长在这里插入图片描述
  3. 结构体赋值结构体在这里插入图片描述
  4. 配合函数指针在这里插入图片描述

5. 运行演示

  1. 添加联系人:在这里插入图片描述
  2. 查找联系人:在这里插入图片描述
  3. 显示所有联系人:在这里插入图片描述
  4. 根据年龄或姓名排序:在这里插入图片描述
    在这里插入图片描述
  5. 修改联系人信息:在这里插入图片描述
  6. 删除所有联系人:
    在这里插入图片描述

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

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

相关文章

探索公共厕所的数字化治理,智慧公厕完善公共厕所智能化的治理体系

随着城市化进程的不断发展&#xff0c;公共厕所治理成为一个不容忽视的问题。如何通过数字化手段来提升公共厕所管理水平&#xff0c;成为了一个备受关注的话题。本文将以智慧公厕领先厂家广州中期科技有限公司&#xff0c;大量精品案例项目实景实图&#xff0c;探讨公共厕所数…

使用transformers进行端到端的目标检测

目录 目标检测的旧方法 使用transformers进行端到端的目标检测 抛去了目标检测旧的方法 网络架构 Transformer encoder Transformers and Parallel Decoding 注意力起到的作用 使用Hungarian algorithm算法完成匹配 在使用transformers的端到端目标检测中&#xff0c;匈…

【开发篇】七、RedisTemplate与StringRedisTemplate + Jedis与Lettcus

文章目录 1、RedisTemplate详解2、常用方法3、关于IDEA的报黄4、RedisTemplate和StringRedisTemplate的区别5、如何通用RedisTemplate和StringRedisTemplate6、Jedis7、Jedis的连接池8、封装Jedis工具类8、RedisTemplate底层实现技术切换 1、RedisTemplate详解 RedisTemplate是…

spark Structured报错解决

报错&#xff0c;不想看原因的直接去解决方案试试 Exception in thread "main" java.lang.IllegalArgumentException: Pathname /C:/Users/Administrator/AppData/Local/Temp/1/temporary-611514af-8dc5-4b20-9237-e5f2d21fdf88/metadata from hdfs://master:8020/C…

C语言的stdio.h的介绍

C语言的stdio.h的介绍 C语言的stdio.h的介绍 C语言的stdio.h的介绍C语言stdio.h的介绍 C语言stdio.h的介绍 这个含义是导入标准输入输出库 包含头文件.h&#xff0c;std标准库&#xff0c;io是input output输入输出库 <>代表系统库&#xff0c;自定义的话用""…

Ingress Controller

什么是 Ingress Controller &#xff1f; 在云原生生态中&#xff0c;通常来讲&#xff0c;入口控制器( Ingress Controller )是 Kubernetes 中的一个关键组件&#xff0c;用于管理入口资源对象。 Ingress 资源对象用于定义来自外网的 HTTP 和 HTTPS 规则&#xff0c;以控制进…

解决typescript报错:不能将类型xxx分配给类型xxx

现象&#xff1a; 这种情况是因为组件传参时&#xff1a; 等号左右两边的数据类型不能严格匹配一致造成的 等号左边data, 查看一下被传参的子组件ProductList的内部data属性: 可以看到data的类型是 &#xff1a; Product[] 而右边的shoppingCartItems来自于&#xff1a; redu…

作为一名独立开发者,如何获取客户?

很多程序员想成为一名独立开发者&#xff0c;从事自由职业&#xff0c;最大的困难在于如何赚钱&#xff0c;进一步来说&#xff0c;就是如何找到自己的客户&#xff0c;有很多开发者拥有丰富的经验&#xff0c;优秀的能力&#xff0c;但无法吸引客户。这篇文章的灵感正是为此而…

精通git,没用过git cherry-pick?

前言 git cherry-pick是git中非常有用的一个命令&#xff0c;cherry是樱桃的意思&#xff0c;cherry-pick就是挑樱桃&#xff0c;从一堆樱桃中挑选自己喜欢的樱桃&#xff0c;在git中就是多次commit中挑选一个或者几个commit出来&#xff0c;也可以理解为把特定的commit复制到…

Spring整合第三方框架-MyBatis原始操作代码

建议自己写一下 实体类&#xff0c;用于封装数据库数据 package com.example.pojo;import java.util.Date;public class Emp {private Integer id;private String username;private String password;private String name;private Integer gender;private String image;privat…

网络安全内网渗透之DNS隧道实验--dnscat2直连模式

目录 一、DNS隧道攻击原理 二、DNS隧道工具 &#xff08;一&#xff09;安装dnscat2服务端 &#xff08;二&#xff09;启动服务器端 &#xff08;三&#xff09;在目标机器上安装客户端 &#xff08;四&#xff09;反弹shell 一、DNS隧道攻击原理 在进行DNS查询时&#x…

Redis可视化工具-Another Redis Desktop Manager 安装

Another Redis DeskTop Manager 是 Redis 可视化管理工具&#xff0c;体积小&#xff0c;完全免费。最重要的是稳定&#xff0c;而且操作简单、方便。 目录 一、下载安装 下载 安装 二、简单使用 连接 新增key 三、springboot整合redis 前期准备 一、下载安装 下载 下载…

ARM IIC总线实现温湿传感器

IIC.h #ifndef __IIC_H__ #define __IIC_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h"/* 通过程序模拟实现I2C总线的时序和协议* GPIOF ---> AHB4* I2C1_SCL ---> PF14* I2C1_SDA ---> PF15** */#define SET_SDA_OUT do{G…

数据库选型参考

文章目录 前言嵌入式数据库数据库服务器PostgreSQL和MySQL的对比 NoSQL国产数据库阿里PolarDB腾讯TDSQL阿里OceanBase和PolarDB的区别 华为GaussDb 前言 DB-Engines Ranking 会根据受欢迎程度对数据库管理系统进行排名&#xff0c;排名每月更新一次。 分为关系型数据库、Key-V…

SpringMVC 学习(七)JSON

9. JSON 9.1 简介 JSON&#xff08;JavaScript Object Notation&#xff0c;JS 对象标记&#xff09;是一种轻量级数据交换格式&#xff0c;采用独立于编程语言的文本格式储存和表示数据&#xff0c;易于机器解析和生成&#xff0c;提升网络传输效率。 任何 JavaScript 支持…

9.26 牛客Java题库day 3

1.类变量&#xff08;static&#xff09;在不设置初始值时,会进行默认值赋值&#xff0c;而局部方法中声明的变量则必须进行初始化&#xff0c;它不会进行默认值赋值 2.了解forward,redirect: URL:统一资源定位符&#xff0c;又是也被俗称为网页地址 http://www.runoob.com/…

描述性统计分析

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件可在个人主页—…

电压放大器在无损探伤中的应用研究

电压放大器是一种常见的电子设备&#xff0c;其主要作用是将低电平信号转换为高电平信号。在无损探伤中&#xff0c;电压放大器被广泛应用于信号增益和分析&#xff0c;以便更好地检测表面或内部缺陷。下面安泰电子Aigtek将详细介绍电压放大器在无损探伤中的应用研究。 电压放大…

ForkJoin详解

1.分支合并 (大数据量的去使用) package com.kuang.forkjoin;import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.function.LongBinaryOperator; import java.util.stre…

MSF的安装与使用教程,超详细,附安装包和密钥

MSF简介 Metasploit&#xff08;MSF&#xff09;是一个免费的、可下载的框架 它本身附带数百个已知软件漏洞&#xff0c;是一款专业级漏洞攻击工具。 当H.D. Moore在2003年发布Metasploit时&#xff0c;计算机安全状况也被永久性地改变了&#xff0c;仿佛一夜之间&#xff0…