当前位置: 首页 > news >正文

C语言之指针进阶篇(3)

目录

思维导图

回调函数

案例1—计算器

案例2—qsort函数

关于qsort函数  

演示qsort函数的使用

案例3—冒泡排序 

整型数据冒泡排序

回调函数搞定各类型冒泡排序

cmp_int比较大小

 cmp传参数

NO1.

NO2.

解决方案

交换swap

总代码


今天我们学习指针难点之回调函数🆗🆗🆗。

首先我们用思维导图回顾一下前面的内容。

思维导图

回调函数

回调函数就是一个通过函数指针调用的函数。

如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

案例1—计算器

就前文我们学习的计算器,我们再用回调函数来解决一下!🆗🆗🆗

#define _CRT_SECURE_NO_WARNINGS 1
//计算器
#include<stdio.h>
void meau()
{printf("**************************\n");printf("** 1.add   2.sub      ****\n");printf("** 3.mul   4.div      ****\n");printf("** 0.exit            *****\n");printf("**************************\n");
}
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int input = 0;int x = 0;int y = 0;int ret = 0;do{meau();printf("请选择>");scanf("%d", &input);switch (input){case 1:printf("请输入2个操作数:");scanf("%d %d", &x, &y);ret = Add(x, y);printf("ret=%d\n", ret);break;case 2:printf("请输入2个操作数:");scanf("%d %d", &x, &y);ret = Sub(x, y);printf("ret=%d\n", ret);break;case 3:printf("请输入2个操作数:");scanf("%d %d", &x, &y);ret = Mul(x, y);printf("ret=%d\n", ret);break;case 4:printf("请输入2个操作数:");scanf("%d %d", &x, &y);ret = Div(x, y);printf("ret=%d\n", ret);break;case 0:printf("退出游戏");break;default:printf("选择错误,重新选择\n");break;}} while (input);return 0;
}

回调函数 

#define _CRT_SECURE_NO_WARNINGS 1
//计算器
#include<stdio.h>
void meau()
{printf("**************************\n");printf("** 1.add   2.sub      ****\n");printf("** 3.mul   4.div      ****\n");printf("** 0.exit            *****\n");printf("**************************\n");
}
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
void calc(int(*p)(int, int))//函数指针传参
{int x = 0;int y = 0;printf("请输入两个操作数\n");scanf("%d %d", &x, &y);int ret = p(x, y);//函数调用printf("ret=%d\n", ret);
}
int main()
{int input = 0;do{meau();printf("请选择>\n");scanf("%d", &input);switch (input){case 1:calc(&Add);break;case 2:calc(&Sub);break;case 3:calc(Mul);break;case 4:calc(Div);break;case 0:printf("退出游戏");break;default:printf("选择错误,重新选择\n");break;}} while (input);return 0;
}

解释如下: 

在main函数中,没有直接去调用函数。而是把函数指针传参给另外的一个函数calc,在calc内部使用函数指针调用,通过函数指针就可以找到指针指向的函数,此刻被指向的函数就是回调函数。

像上图所示,通过calc函数调用Add函数指针,找到Add函数,就把Add函数称为回调函数

calc称为回调函数的机制

老板>>组长>>员工

案例2—qsort函数

那出了上面回调函数的案例,还有一个经典回调函数的案例:qsort

 qsort是一个库函数,底层使用的是快速排序的方式,对不同数据进行排序的。

这个函数可以直接使用。

这个函数可以用来排序任意类型的数据。

对数据进行排序方法很多:

冒泡排,序选择排序,插入排序,快速排序等等。 

关于qsort函数  

关于qsort函数的点--->qsort - C++ Reference (cplusplus.com)

需要包含头文件#include<stdlib.h>

  •  排序整型数组,两个整型可以直接使用>比较
  • 排序结构体数组,两个结构体的数据可能不能直接使用>比较

也就是不同类型的数据,比较大小的方法是有差异的

最后一个参数,排序不同数据的重要点,需要封装不同的函数去比较不同的数据的大小

void qsort(void* base, //指向了待排序数组第一个元素的首地址size_t num, //待排序数组的元素个数size_t size,//每个待排序数组元素的大小int (*compar)(const void* e1, const void* e2));
//函数指针,compar指向了一个函数,这个函数是用来比较两个元素的大小,
//e1和e2存放的是两个元素的地址
//在qsort内部调用这个函数,指向这个函数,这个函数就被称为回调函数
// 
//qsort内部怎么排序我们不需要过多去探讨
//const也暂不做讲解//因为不知道要比较的元素类型,所以我们使用void*指针的类型,来统一存放各种类型的指针

那怎样通过元素地址,去比较两个元素数据的大小呢? 

以int的数据为例:将void*类型的数据强制转化成(int*),再作差

当e1>e2,函数返回>0的值;

当e1<e2,函数返回<0的值;

当e1=e2,函数返回=0

void compar_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}

那有人询问为什么不直接对元素地址const void* e1和 const void* e2解引用?

作为void*指针不能直接解引用。

void* 类型的指针—不能进行解引用操作符,也不能进行+-整数的操作
void* 类型的指针是用来存放任意类型数据的地址
void* 无具体类型的指针
void*和int*和char*一样都是指针类型

#include<stdio.h>
int main()
{char a = 'x';char* pa = &a;int b = 1;void* p = &b;//存放int*p = &a;//存放char*return 0;
}

演示qsort函数的使用

#include<stdio.h>
#include<stdlib.h>
void print(int arr[], int sz)
{int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}
}void qsort(void* base, size_t num,size_t size,int (*compar)(const void*, const void*));void compar_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}
void test1()
{int arr[] = { 10,9,8,7,6,5,4,3,2,1 };int sz = sizeof(arr) / sizeof(arr[0]);print(arr, sz);printf("\n");qsort(arr, sz, sizeof(arr[0]), compar_int);print(arr, sz);
}int main()
{test1();test2();return 0;
}

以上我只是以整型为例,结构体数据数组也是一样的逻辑,大家可以自行分析。

下面结构体:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>//?void qsort(void* base,size_t num,size_t size,int (*compar)(const void*, const void*));struct Stu
{char name[20];int age;
};
//结构体数据怎么比较呢?
//按照年龄比较
//按照名字比较//按照年龄
void compar_stu_by_age(const void* e1, const void* e2)
{return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;//return (*(struct Stu*)e1).age - (*(struct Stu*)e2).age;
}
void test2()
{struct Stu arr[] = { {"zhangsan",20},{"lisi",30},{"wangwu",12} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), compar_stu_by_age);}
//按照名字
void compar_stu_by_name(const void* e1, const void* e2)
{return ((struct Stu*)e1)->name - ((struct Stu*)e2)->name;//return (*(struct Stu*)e1).name - (*(struct Stu*)e2).name;
}
void test2()
{struct Stu arr[] = { {"zhangsan",20},{"lisi",30},{"wangwu",12} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), compar_stu_by_name);}int main()
{test2();return 0;
}

只要qsort函数使用得当,可以对任何数据进行排序!🆗🆗 

案例3—冒泡排序 

(使用回调函数,模拟实现qsort(采用冒泡的方式)

整型数据冒泡排序

(这种方式只能排列整数,存在局限性)

//冒泡排序
#include<stdio.h>
void bubble_sort(int arr[], int sz)
{int i = 0;for (i = 0; i < sz - 1; i++){int j = 0;for (j = 0; j < sz - 1 - i; j++){if (arr[j] > arr[j + 1]){int tmp = 0;tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}
void print_arr(int arr[], int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}
}
int main()
{int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz);print_arr(arr, sz);
}

回调函数搞定各类型冒泡排序

 经过分析冒泡排序,我们得到

void bubble_sort(void* base, size_t num, size_t size,

                            int (*cmp)(const void* e1, const void* e2))

cmp_int比较大小

以整型为例 

int (*cmp)(const void* e1, const void* e2)

e1是一个指针,存放了一个要比较的元素的地址。

e2是一个指针,存放了一个要比较的元素的地址。

e1指向的元素>e2指向的元素,返回>0的数字。

e1指向的元素<e2指向的元素,返回>0的数字。

e1指向的元素==e2指向的元素,返回>0的数字。

cmp是函数指针指向一个我们程序想要待排序的数组。

将比较函数cmp_int的地址传给cmp即可。

//比较大小
void cmp_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}
//这里就是将cmp_int的地址在调用函数bubble_sort时将其传过去即可。
 cmp传参数
NO1.

有同学提出直接对待排序的数组首元素地址解引用找到e1的地址,然后通过一个元素的大小或者+1可以找到e2的地址,可以吗?当然不可以

  • 作为void*指针不能直接解引用。

    void* 类型的指针—不能进行解引用操作符,也不能进行+-整数的操作
    void* 类型的指针是用来存放任意类型数据的地址
    void* 无具体类型的指针
    void*和int*和char*一样都是指针类型

NO2.

有同学又提出那将void*的指针强制转换成我们想要的int*或double*等,再+1可以吗?           不可以,理由就是,强制转换存在在于我们公共的bubble_sort排序函数中时不能随着待排序的数组数据类型不同而改变,我们只能改变不同数据类型的不同比较方法。

解决方案

 

			//if(arr[j]>arr[j+1])if (cmp( (char*)base+j*size,(char*)base+(j+1)*size )>0){int tmp = 0;tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}
交换swap

当我们只知道元素的起始地址,并不知道元素的类型所以我们并没有合适的中间值类型tmp创建。所以我们换一种方法。

我们已知元素e1和e2的起始地址每个元素的大小

那我们可以用一个一个char类型的数据交换用for循环

直到每个元素的大小size结束,也就是元素交换完成。

 

//交换数据
void change(char* buf1, char* buf2,size_t size)
{char i = 0;for (i = 0; i < size; i++){char tmp = 0;tmp = *buf1;*buf1=*buf2;*buf2 = tmp;buf1++;//*buf1++buf2++;//*buf2++}
}
总代码
//冒泡排序
#include<stdio.h>
void print_arr(int arr[], int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}
}void bubble_sort(void* base, size_t num, size_t size,int (*cmp)(const void* e1, const void* e2))
{int i = 0;for (i = 0; i < num - 1; i++){int j = 0;for (j = 0; j < num - 1 - i; j++){//if(arr[j]>arr[j+1])if (cmp( (char*)base+j*size,(char*)base+(j+1)*size )>0){change((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}
//交换数据
void change(char* buf1, char* buf2,size_t size)
{char i = 0;for (i = 0; i < size; i++){char tmp = 0;tmp = *buf1;*buf1=*buf2;*buf2 = tmp;buf1++;//*e1++buf2++;//*e2++}
}
//比较大小
void cmp_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;//>0
}void test1()
{int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);print_arr(arr, sz);printf("\n");bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);print_arr(arr, sz);
}int main()
{test1();
}

当然我们也可以用结构体类型去测试一下! 🆗🆗试试

✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!旗鼓相当

代码------→【gitee:唐棣棣 (TSQXG) - Gitee.com】

联系------→【邮箱:2784139418@qq.com】

相关文章:

C语言之指针进阶篇(3)

目录 思维导图 回调函数 案例1—计算器 案例2—qsort函数 关于qsort函数 演示qsort函数的使用 案例3—冒泡排序 整型数据冒泡排序 回调函数搞定各类型冒泡排序 cmp_int比较大小 cmp传参数 NO1. NO2. 解决方案 交换swap 总代码 今天我们学习指针难点之回调函数…...

SQL7 查找年龄大于24岁的用户信息

描述 题目&#xff1a;现在运营想要针对24岁以上的用户开展分析&#xff0c;请你取出满足条件的设备ID、性别、年龄、学校。 用户信息表&#xff1a;user_profile iddevice_idgenderageuniversityprovince12138male21北京大学Beijing23214male复旦大学Shanghai36543female20…...

vite搭建vue3项目

参考视频 1.使用npm搭建vite项目,会自动搭建vue3项目 npm create vitelatest yarn create vite2.手动搭建vue3项目 创建一个项目名称的文件夹执行命令&#xff1a;npm init -y 快速的创建一个默认的包信息安装vite: npm i vite -D -D开发环境的依赖 安装vue,现在默认是vue3.…...

Qt中表格属性相关操作,调整表格宽度高度自适应内容等

1 表格列宽设置 利用Qt designer设计&#xff0c;可以通过改变表头的列宽从而保证内容不会被遮盖&#xff0c;输入空格的方式增加表头的长度&#xff0c;比如表头为"Value"&#xff0c;则改成"Value "&#xff0c;可以扩展列默认的宽度&#xff0c;保证后面…...

NLP机器翻译全景:从基本原理到技术实战全解析

目录 一、机器翻译简介1. 什么是机器翻译 (MT)?2. 源语言和目标语言3. 翻译模型4. 上下文的重要性 二、基于规则的机器翻译 (RBMT)1. 规则的制定2. 词典和词汇选择3. 限制与挑战4. PyTorch实现 三、基于统计的机器翻译 (SMT)1. 数据驱动2. 短语对齐3. 评分和选择4. PyTorch实现…...

docker四种网络模式

文章目录 一.为什么要了解docker网络二.docker 网络理论三.docker的四类网络模式3.1 bridge模式3.2 host模式3.3 container模式3.4 none模式 四.bridge模式下容器的通信4.1 防火墙开启状态4.2 防火墙关闭状态 一.为什么要了解docker网络 当你开始大规模使用Docker时&#xff0…...

C 风格文件输入/输出---无格式输入/输出---(std::fgetc,std::getc,std::fgets)

C 标准库的 C I/O 子集实现 C 风格流输入/输出操作。 <cstdio> 头文件提供通用文件支持并提供有窄和多字节字符输入/输出能力的函数&#xff0c;而 <cwchar>头文件提供有宽字符输入/输出能力的函数。 无格式输入/输出 从文件流获取字符 std::fgetc, std::getc …...

多线程之间如何进行通信 ?

实现多线程之间通信的方式有多种,以下是一些常见的方式: 共享变量:多个线程共享一个变量,通过互斥锁(如synchronized关键字)来保护对该变量的访问,确保线程之间的安全通信。 wait() 和 notify() / notifyAll():通过Object类的wait()方法使线程等待,然后使用notify()或…...

二叉树顺序存储结构

目录 1.二叉树顺序存储结构 2.堆的概念及结构 3.堆的相关接口实现 3.1 堆的插入及向上调整算法 3.1.1 向上调整算法 3.1.2 堆的插入 3.2 堆的删除及向下调整算法 3.2.1 向下调整算法 3.2.2 堆的删除 3.3 其它接口和代码实现 4.建堆或数组调堆的两种方式及复杂度分析…...

Apache HTTPD 多后缀解析漏洞复现

Apache HTTPD 支持一个文件拥有多个后缀&#xff0c;并为不同后缀执行不同的指令。比如&#xff0c;如下配置文件&#xff1a; AddType text/html .html AddLanguage zh-CN .cn 其给.html后缀增加了media-type&#xff0c;值为text/html&#xff1b;给.cn后缀增加了语言&…...

【深入浅出C#】章节10: 最佳实践和性能优化:内存管理和资源释放

一、 内存管理基础 1.1 垃圾回收机制 垃圾回收概述 垃圾回收&#xff08;Garbage Collection&#xff09;是一种计算机科学和编程领域的重要概念&#xff0c;它主要用于自动管理计算机程序中的内存分配和释放。垃圾回收的目标是识别和回收不再被程序使用的内存&#xff0c;以…...

我的创作纪念日——1个普通网安人的漫谈

机缘 大家好&#xff0c;我是zangcc。今天突然收到了一条私信&#xff0c;才发现来csdn已经1024天了&#xff0c;不知不觉都搞安全渗透2年半多了&#x1f414;&#xff0c;真是光阴似箭。 我写博客的初衷只是记录自己的学习历程&#xff0c;比如打打靶场&#xff0c;写一下通关…...

Linux中执行bash脚本报错/bin/bash^M: bad interpreter: No such file or directory

文章目录 参考博客&#xff1a; Linux中执行bash脚本报错/bin/bash^M: bad interpreter: No such file or directory 首先在此对这位博主表示感谢。 运行bash脚本会出现两个文件&#xff0c;1037.err和1037.out。 1037.err的文件内容如下&#xff1a; /data/home/user12/.lsbat…...

期权交易策略主要有哪些?期权交易策略指南

在学习更复杂的看涨和看跌期权策略之前&#xff0c;普通投资者应该彻底了解一些关于期权的基本知识&#xff0c;这样有助你后期的交易能力和理论知识水平提升有很大的帮助&#xff0c;下文科普期权交易策略主要有哪些&#xff1f;期权交易策略指南&#xff01;本文来自&#xf…...

算法通关村第十四关——解析堆在数组中找第K大的元素的应用

力扣215题&#xff0c; 给定整数数组nums和整数k&#xff0c;请返回数组中第k个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第k个最大的元素&#xff0c;而不是第k个不同的元素。 分析&#xff1a;按照“找最大用小堆&#xff0c;找最小用大堆&#xff0c;找中间…...

【报错】springboot3启动报错

报错内容&#xff1a;Cannot load driver class: org.h2.Driver Error starting ApplicationContext. To display the condition evaluation report re-run your application with debug enabled. 解决; 通过源码分析&#xff0c;druid-spring-boot-3-starter目前最新版本是1…...

阿里云服务器配置怎么选择?小白攻略

阿里云服务器配置选择_CPU内存/带宽/存储配置_小白指南&#xff0c;阿里云服务器配置选择方法包括云服务器类型、CPU内存、操作系统、公网带宽、系统盘存储、网络带宽选择、安全配置、监控等&#xff0c;阿小云分享阿里云服务器配置选择方法&#xff0c;选择适合自己的云服务器…...

关于 RK3568的linux系统killed用户应用进程(用户现象为崩溃) 的解决方法

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/132710642 红胖子网络科技博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…...

EasyPHP-Devserver-17安装和配置mantisBT

文章目录 1、准备工作2、安装easyphp2.1 http://127.0.0.1 无法访问 3、安装mantisBT和phpMyAdmin3.1 配置浏览器的访问url和端口号&#xff08;配置局域网内可访问&#xff09;3.2 安装mantis 4、Administrator 注册新用户时设置登录密码5、附件上传6、邮件配置 文章参考自&am…...

Python打包教程 PyInstaller和cx_Freeze

当我们开发Python应用程序时&#xff0c;通常会将代码保存在.py文件中&#xff0c;然后通过Python解释器运行它。这对于开发和测试是非常方便的&#xff0c;但在将应用程序分享给其他人或在不同环境中部署时&#xff0c;可能会带来一些问题。为了解决这些问题&#xff0c;我们可…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...