设计一个简单的通讯录

目录

导读:

一、主函数

1. 打印功能菜单

2. 用枚举常量列举功能给功能赋值(0-5)

3. main主函数

二、头文件

三、通讯录各功能的实现

1. 初始化通讯录

2. 增加联系人

3. 展示所有联系人信息

4.  删除指定联系人

5. 查询指定联系人信息

6. 修改指定联系人信息

7. 销毁通讯录

四、各模块全部代码

1. 主函数

2. 头文件

3. 功能实现

五、代码运行展示

1. 添加联系人

2. 展示联系人信息

​3. 查找联系人

4. 修改联系人并展示

5. 删除联系人并展示

6. 退出通讯录 


导读:

通讯录中所涉及到的动态内存管理相关知识在:

C语言动态内存管理(malloc, calloc,realloc)详解-CSDN博客

柔性数组:

柔性数组详解-CSDN博客

结构体等自定义类型相关知识:

结构体、枚举以及联合类型在内存中的存储与大小计算-CSDN博客

还有之前写过的一个简易的三子棋游戏:

三子棋小游戏代码实现_流浪者与猴的博客-CSDN博客

该通讯录功能为增、删、查、改以及展示目前存放的所有联系人信息,更多功能以及优化等待博主后续的努力

该代码分三个模块:主函数(test_16.c)、具体功能的实现(contact.c)、以及函数的声明(contact.h)

一、主函数

在开头引用contact.h头文件,函数内涵所用到的所有函数以及结构体声明

#include "contact.h"

1. 打印功能菜单

void menu()
{printf("***************************************\n");printf("**** 1.add          2.del    **********\n");printf("**** 3.search       4.modify **********\n");printf("**** 5.show         0.exit     **********\n");printf("***************************************\n");
}

2. 用枚举常量列举功能给功能赋值(0-5)

enum Option  //列举出通讯录功能
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,
};

3. main主函数

使用do...while循环以及switch来实现功能的反复使用,其中的结构体和函数声明在自身创的头文件中,再开头以及引用

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:ShowContact(&con);break;case EXIT:DestroyContact(&con);//销毁空间printf("退出\n");break;default:printf("输入错误,请重新输入\n");break;}} while (input);return 0;
}

二、头文件

头文件中包括库函数、各功能函数、结构体等声明,以供在其他模块更好的使用

#pragma once
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_MAX 20   
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 100
#define DEFAULT_SZ 3
#define DEFAULT_INC 2//类型的声明
typedef struct PeoInfo
{char name[NAME_MAX];int age;char sex[SEX_MAX];char tele[TELE_MAX];char addr[ADDR_MAX];
}PeoInfo;
//静态
//typedef struct Contact
//{
//	PeoInfo data[MAX];//存放数据
//	int sz;//记录当前通讯录中存在的人的信息个数
//}Contact;//动态
typedef struct Contact
{PeoInfo* data;//存放数据int sz;//记录当前通讯录中存在的人的信息个数int capacity;//记录的是通讯录的当前容量
}Contact;//初始化通讯录
void InitContact(Contact* pc);//增加联系人
void AddContact(Contact* pc);//显示所有联系人
void ShowContact(Contact* pc);//删除指定联系人
void DelContact(Contact* pc);//查找指定联系人
void SearchContact(Contact* pc);//修改指定联系人
void ModifyContact(Contact* pc);//销毁通讯录
void DestroyContact(Contact* pc);

三、通讯录各功能的实现

1. 初始化通讯录

void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;  //初始通讯录个人信息为0pc->capacity = DEFAULT_SZ; // 通讯录初始容量为3pc->data = calloc(pc->capacity, sizeof(PeoInfo));//为存放数据开辟内存if (pc->data == NULL){perror("calloc");//如果没有开辟成功返回报错信息return;}memset(pc->data, 0, sizeof(pc->data));//开辟成功,把数据初始化为0
}

2. 增加联系人

在增加联系人前,需要检查通讯录的容量是否够用,这里单独分装成一个函数,来实现容量的检查以及扩展

void CheckCapacity(Contact* pc) //检查容量大小
{if (pc->sz == pc->capacity)//增加的当前人的数量与容量相等{PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));//给data重新开辟空间if (ptr != NULL){pc->data = ptr;//开辟成功则把空间赋给datapc->capacity += DEFAULT_INC;//让容量自增2个printf("增容成功\n");}else{perror("AddContact->realloc");//开辟失败返回报错信息return;}}
}
void AddContact(Contact* pc)//增加联系人
{assert(pc);CheckCapacity(pc);//查看容量,容量不够则增加//增加信息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");
}

3. 展示所有联系人信息

void ShowContact(Contact* pc)//展示所有联系人信息
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无需打印\n");return;}int i = 0;//名字	年龄	性别	电话	地址printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");for (i = 0; i < pc->sz; i++){//打印每个人信息printf("%-20s%-5d%-5s%-12s%-30s\n",pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);}
}

4.  删除指定联系人

删除联系人需要对通讯录进行查找,所有这里我们也时再次分装一个函数用来查找联系人,后续联系人信息的修改以及查询某个联系人同样需要此函数

int FindByName(Contact* pc, char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->sz; i++)//进入循环逐个查找{if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;//找不到
}

开始删除

void DelContact(Contact* pc)//删除指定联系人
{char name[NAME_MAX];assert(pc);if (pc->sz == 0)//如果当前通讯录并没有增加任何联系人,则返回{printf("通讯录为空,无法删除\n");return;}//找到联系人printf("输入删除人的名字:");scanf("%s", name);//找到名字为name的人int ret = FindByName(pc, name);if (ret == -1){printf("要删除得到人不存在\n");return;}//删除这个人int i = 0;for (i = ret; i < pc->sz-1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");
}

5. 查询指定联系人信息

这里也用了查找函数

void SearchContact(Contact* pc)//查询联系人
{assert(pc);char name[NAME_MAX];printf("输入查找人的名字:");scanf("%s", name);//找到名字为name的人int ret = FindByName(pc, name);if (ret == -1){printf("要查找的人不存在\n");return;}//显示出来printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s%-5d%-5s%-12s%-30s\n",pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}

6. 修改指定联系人信息

void ModifyContact(Contact* pc)修改指定联系人
{assert(pc);char name[NAME_MAX];printf("输入要修改人的名字:");scanf("%s", name);//找到名字为name的人int ret = FindByName(pc, name);if (ret == -1){printf("要修改的人不存在\n");return;}//修改printf("请输入名字:");scanf("%s", pc->data[ret].name);printf("请输入年龄:");scanf("%d", &pc->data[ret].age);printf("请输入性别:");scanf("%s", pc->data[ret].sex);printf("请输入电话:");scanf("%s", pc->data[ret].tele);printf("请输入地址:");scanf("%s", pc->data[ret].addr);
}

7. 销毁通讯录

开辟的内存使用后需要进行释放

void DestroyContact(Contact* pc)//开辟的内存使用后需要进行释放
{free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;
}

四、各模块全部代码

1. 主函数

#define _CRT_SECURE_NO_WARNINGS 
#include "contact.h"
//测试通讯录的基本功能
void menu()
{printf("***************************************\n");printf("**** 1.add          2.del    **********\n");printf("**** 3.search       4.modify **********\n");printf("**** 5.show         0.exit     **********\n");printf("***************************************\n");
}
enum Option  //列举出通讯录功能
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,
};
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:ShowContact(&con);break;case EXIT:DestroyContact(&con);//销毁空间printf("退出\n");break;default:printf("输入错误,请重新输入\n");break;}} while (input);return 0;
}

2. 头文件

#pragma once
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_MAX 20   
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 100
#define DEFAULT_SZ 3
#define DEFAULT_INC 2//类型的声明
typedef struct PeoInfo
{char name[NAME_MAX];int age;char sex[SEX_MAX];char tele[TELE_MAX];char addr[ADDR_MAX];
}PeoInfo;
//静态
//typedef struct Contact
//{
//	PeoInfo data[MAX];//存放数据
//	int sz;//记录当前通讯录中存在的人的信息个数
//}Contact;//动态
typedef struct Contact
{PeoInfo* data;//存放数据int sz;//记录当前通讯录中存在的人的信息个数int capacity;//记录的是通讯录的当前容量
}Contact;//初始化通讯录
void InitContact(Contact* pc);//增加联系人
void AddContact(Contact* pc);//显示所有联系人
void ShowContact(Contact* pc);//删除指定联系人
void DelContact(Contact* pc);//查找指定联系人
void SearchContact(Contact* pc);//修改指定联系人
void ModifyContact(Contact* pc);//销毁通讯录
void DestroyContact(Contact* pc);

3. 功能实现

#define _CRT_SECURE_NO_WARNINGS 
#include "contact.h"
//静态
//void InitContact(Contact* pc)
//{
//	assert(pc);
//	pc->sz = 0;
//	memset(pc->data, 0, sizeof(pc->data));
//}//动态
void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;  //初始通讯录个人信息为0pc->capacity = DEFAULT_SZ; // 通讯录初始容量为3pc->data = calloc(pc->capacity, sizeof(PeoInfo));//为存放数据开辟内存if (pc->data == NULL){perror("calloc");//如果没有开辟成功返回报错信息return;}memset(pc->data, 0, sizeof(pc->data));//开辟成功,把数据初始化为0
}//静态版本
//void AddContact(Contact* pc)
//{
//	assert(pc);
//	if (pc->sz == MAX)
//	{
//		printf("通讯录已满,无法增加\n");
//		return;
//	}
//	//增加信息
//	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 CheckCapacity(Contact* pc) //检查容量大小
{if (pc->sz == pc->capacity)//增加的当前人的数量与容量相等{PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));//给data重新开辟空间if (ptr != NULL){pc->data = ptr;//开辟成功则把空间赋给datapc->capacity += DEFAULT_INC;//让容量自增2个printf("增容成功\n");}else{perror("AddContact->realloc");//开辟失败返回报错信息return;}}
}
void DestroyContact(Contact* pc)//开辟的内存使用后需要进行释放
{free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;
}
void AddContact(Contact* pc)//增加联系人
{assert(pc);CheckCapacity(pc);//查看容量,容量不够则增加//增加信息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 ShowContact(Contact* pc)//展示所有联系人信息
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无需打印\n");return;}int i = 0;//名字	年龄	性别	电话	地址printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");for (i = 0; i < pc->sz; i++){//打印每个人信息printf("%-20s%-5d%-5s%-12s%-30s\n",pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);}
}int FindByName(Contact* pc, char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->sz; i++)//进入循环逐个查找{if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;//找不到
}
void DelContact(Contact* pc)//删除指定联系人
{char name[NAME_MAX];assert(pc);if (pc->sz == 0)//如果当前通讯录并没有增加任何联系人,则返回{printf("通讯录为空,无法删除\n");return;}//找到联系人printf("输入删除人的名字:");scanf("%s", name);//找到名字为name的人int ret = FindByName(pc, name);if (ret == -1){printf("要删除得到人不存在\n");return;}//删除这个人int i = 0;for (i = ret; i < pc->sz-1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");
}void SearchContact(Contact* pc)//查询指定联系人
{assert(pc);char name[NAME_MAX];printf("输入查找人的名字:");scanf("%s", name);//找到名字为name的人int ret = FindByName(pc, name);if (ret == -1){printf("要查找的人不存在\n");return;}//显示出来printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s%-5d%-5s%-12s%-30s\n",pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}void ModifyContact(Contact* pc)修改指定联系人
{assert(pc);char name[NAME_MAX];printf("输入要修改人的名字:");scanf("%s", name);//找到名字为name的人int ret = FindByName(pc, name);if (ret == -1){printf("要修改的人不存在\n");return;}//修改printf("请输入名字:");scanf("%s", pc->data[ret].name);printf("请输入年龄:");scanf("%d", &pc->data[ret].age);printf("请输入性别:");scanf("%s", pc->data[ret].sex);printf("请输入电话:");scanf("%s", pc->data[ret].tele);printf("请输入地址:");scanf("%s", pc->data[ret].addr);
}

五、代码运行展示

1. 添加联系人

2. 展示联系人信息

3. 查找联系人

 4. 修改联系人并展示

5. 删除联系人并展示

6. 退出通讯录 

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

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

相关文章

elasticsearch+logstash+kibana整合(ELK的使用)第一课

一、安装elasticsearch 0、创建目录&#xff0c;统一放到/data/service/elk 1、下载安装包 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.1.0-linux-x86_64.tar.gz2、解压 tar -xzvf elasticsearch-7.1.0-linux-x86_64.tar.gz3、新建用户和组…

FFmpeg 命令:从入门到精通 | FFmpeg 基本介绍

FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 基本介绍 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 基本介绍FFmpeg 简介FFmpeg 基础知识复用与解复用编解码器码率和帧率 资料 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 基本介绍 本系列文章要解决的问题&#xff1…

【SQL】mysql创建定时任务执行存储过程--20230928

1.先设定时区 https://blog.csdn.net/m0_46629123/article/details/133382375 输入命令show variables like “%time_zone%”;&#xff08;注意分号结尾&#xff09;设置时区&#xff0c;输入 set global time_zone “8:00”; 回车,然后退出重启&#xff08;一定记得重启&am…

Web 中间件怎么玩?

本次主要是聊聊关于 web 中间件&#xff0c; 分为如下四个方面 什么是 web 框架中间件 为什么要使用 web 中间件 如何使用及其原理 哪些场景需要使用中间件 开门见山 web 中间件是啥 Web 框架中的中间件主要指的是在 web 请求到具体路由之前或者之后&#xff0c;会经过一个或…

Java进阶必会JVM-深入浅出Java虚拟机

系列文章目录 送书第一期 《用户画像&#xff1a;平台构建与业务实践》 送书活动之抽奖工具的打造 《获取博客评论用户抽取幸运中奖者》 送书第二期 《Spring Cloud Alibaba核心技术与实战案例》 送书第三期 《深入浅出Java虚拟机》 文章目录 系列文章目录前言一、推荐书籍二…

【信创】麒麟v10(arm)-mysql8-mongo-redis-oceanbase

Win10/Win11 借助qume模拟器安装arm64麒麟v10 前言 近两年的国产化进程一直在推进&#xff0c;基于arm架构的国产系统也在积极发展&#xff0c;这里记录一下基于麒麟v10arm版安装常见数据库的方案。 麒麟软件介绍: 银河麒麟高级服务器操作系统V10 - 国产操作系统、银河麒麟、中…

【JavaEE】HTML

JavaWeb HTML 超文本标记语言 超文本&#xff1a;文本、声音、图片、视频、表格、连接标记&#xff1a;有许许多多的标签组成 vscode开发工具搭建 因为我使用的IDEA是社区版&#xff0c;代码高亮补全缩进都有些问题&#xff0c;使用vscode是最好的选择~ 安装 Visual Stu…

机器学习之广义增量规则(Generalized Delta Rule)

文章目录 广义增量规则的公式s型函数的增量规则 广义增量规则的公式 对于单层神经网络的增量规则&#xff0c;已经过时啦&#xff0c;现在存在一种更广义的增量规则形式。对于任意激活函数&#xff0c;增量规则表示如下式它与前一节的delta规则相同&#xff0c;只是ei被替换为…

ElementUI之CUD+表单验证

目录 前言&#xff1a; 增删改查 表单验证 前言&#xff1a; 继上篇博客来写我们的增删改以及表单验证 增删改查 首先先定义接口 数据样式&#xff0c;我们可以去elementUI官网去copy我们喜欢的样式 <!-- 编辑窗体 --><el-dialog :title"title" :visib…

JVM学习笔记

JVM学习笔记 复习之前学的内容&#xff0c;同时补充以下知识点&#xff1a;JVM的双亲委派机制、伊甸区与老年代相关知识&#xff1b; 双亲委派机制 双亲的含义应该就是AppClassLoader有&#xff1a;ExtClassLoader和BootstrapClassLoader“两个”父加载器。 首先介绍Java中…

Java初始化大量数据到Neo4j中(二)

接Java初始化大量数据到Neo4j中(一)继续探索&#xff0c;之前用create命令导入大量数据发现太过耗时&#xff0c;查阅资料说大量数据初始化到Neo4j需要使用neo4j-admin import 业务数据说明可以参加Java初始化大量数据到Neo4j中(一)&#xff0c;这里主要是将处理好的节点数据和…

解决安装 RabbitMQ 安装不成功的问题

由于RabbitMQ是基于erlang的&#xff0c;所以&#xff0c;在正式安装RabbitMQ之前&#xff0c;需要先安装一下erlang。 1、下载mq https://www.rabbitmq.com/download.html 2、下载erlang&#xff08;点击下载路径根据下载的MQ版本对应下载erl版本&#xff09; https://www.…

定义现代化实时数据仓库,SelectDB 全新产品形态全面发布

导读&#xff1a;9 月 25 日&#xff0c;2023 飞轮科技产品发布会在线上正式召开&#xff0c;本次产品发布会以 “新内核、新图景” 为主题&#xff0c;飞轮科技 CEO 马如悦全面解析了现代化数据仓库的演进趋势&#xff0c;宣布立足于多云之上的 SelectDB Cloud 云服务全面开放…

ROS2 库包设置和使用 Catch2 进行单元测试

说明 本文的目的是了解如何在 ROS2 中创建库&#xff0c;以供其他 ROS2 包使用。除此之外&#xff0c;本文还介绍了如何使用 catch2 框架编写单元测试。本文的第 1 部分将详细介绍如何创建库包。第 2 部分将介绍 ROS2 软件包如何利用创建的库 上篇 ROS2 库包设置和使用 Catch2…

stm32 - 初识2

stm32 - 初识2 工程架构点灯程序寄存器方式点灯库函数的方式点灯 工程架构 启动文件 中断向量表&#xff0c;中断服务函数&#xff0c;其他中断等 中断服务函数中的&#xff0c;复位中断是整个程序的入口&#xff0c;调用systeminit&#xff0c;和main函数 点灯程序 寄存器方式…

JAVA 学习笔记 2年经验

文章目录 基础String、StringBuffer、StringBuilder的区别jvm堆和栈的区别垃圾回收标记阶段清除阶段 异常类型双亲委派机制hashmap和hashtable concurrentHashMap 1.7和1.8的区别java的数据结构排序算法&#xff0c;查找算法堆排序 ThreadLocal单例模式常量池synchronizedsynch…

VisionTransformer(ViT)详细架构图

这是原版的架构图&#xff0c;少了很多东西。 这是我根据源码总结出来的详细版 有几点需要说明的&#xff0c;看架构图能看懂就不用看注释了。 &#xff08;1&#xff09;输入图片必须是 224x224x3 的&#xff0c;如果不是就把它缩放到这个尺寸。 &#xff08;2&#xff09;T…

哈希表hash_table

一个人为什么要努力&#xff1f; 我见过最好的答案就是&#xff1a;因为我喜欢的东西都很贵&#xff0c;我想去的地方都很远&#xff0c;我爱的人超完美。文章目录 哈希表的引出unordered系列的关联式容器 底层结构哈希的概念 开放寻址法拉链法&#xff08;哈希桶&#xff09;拉…

睿趣科技:新手抖音开店卖什么产品好

抖音已经成为了一款年轻人热爱的社交媒体应用&#xff0c;同时也成为了一种全新的电商平台。对于新手来说&#xff0c;抖音开店卖什么产品是一个备受关注的问题。在这篇文章中&#xff0c;我们将探讨一些适合新手的产品选择&#xff0c;帮助他们在抖音上开店获得成功。 流行时尚…

面向对象特性分析大全集

面向对象特性分析 先进行专栏介绍 面向对象总析前提小知识分类浅析封装浅析继承浅析多态面向对象编程优点abc 核心思想实际应用总结 封装概念详解关键主要目的核心思想优点12 缺点12 Java代码实现封装特性 继承概念详解语法示例关键主要目的核心思想优点12 缺点12 Java代码实现…