C++指针(四)万字图文详解!
个人主页:PingdiGuo_guo
收录专栏:C++干货专栏
前言
相关文章:C++指针(一)、C++指针(二)、C++指针(三)
本篇博客是介绍函数指针、函数指针数组、回调函数、指针函数的。
点赞破六十,更新下一期哟!
文章目录
前言
1.函数指针
1.1函数指针的概念
1.2函数指针的作用
1.3函数指针的使用
1.3.1定义
1.3.2初始化
1.3.2调用函数
1.3.3比较函数指针
1.4函数指针的练习
2.函数指针数组
2.1函数指针数组的作用
2.2函数指针数组的使用
2.2.1 定义
2.2.2 初始化
2.2.3 调用
2.2.4 传参
2.3函数指针二维数组
2.4函数指针数组的练习
3.回调函数与回调指针
3.1回调函数的用处
3.2回调函数的使用
3.2.1 定义函数原型
3.2.2 声明变量
3.2.3定义
3.2.4 地址传递
3.2.5调用
3.3回调指针
3.3.1回调指针的使用
3.3.2回调函数与回调指针的关系
4.指针函数
4.1指针函数的作用
4.2指针函数的操作
4.2.1 声明
4.2.2 定义
4.2.3 调用
4.2.4返回
4.3指针函数的练习
总结
1.函数指针
大家可能在学习了指针后有这样的疑惑:哎,既然数组有地址,变量有地址,那函数会不会也有地址呀?是的,函数也有地址,请看下面一段代码:
#include <bits/stdc++.h>
using namespace std;
void te()
{printf("hello!\n");
}
int main()
{printf("%p\n", te);printf("%p\n", &te);return 0;
}
输出结果:
函数地址:函数名、&函数名
可要储存怎么办呢?别急,接下来我们要讲的函数指针就是用来存储函数的地址的。
1.1函数指针的概念
函数指针是指可以指向函数的变量。它存储了函数的地址,可以通过函数指针调用对应的函数。在C和C++等编程语言中,函数被编译为一段机器码,该机器码位于内存的某个地址上。函数指针就是存储这个地址的变量,它允许我们通过指针来直接调用对应的函数。
1.2函数指针的作用
函数指针可以用于以下几个方面:
1.回调函数:当一个函数需要在某个事件发生时调用另一个函数时,可以使用函数指针来实现回调函数。比如,当一个操作完成时,可以调用预先设置的回调函数来处理操作结果。
2.排序和搜索算法:函数指针可以用于排序和搜索算法中,通过传递一个比较函数给算法,实现不同的排序顺序或搜索条件。
3.动态库加载:函数指针可以用于加载动态库中的函数。通过函数指针,可以在运行时动态地加载和使用库中的函数。
4.多态性:函数指针可以用于实现多态性,允许在运行时确定要调用的具体函数。
总而言之,函数指针可以增强程序的灵活性,使其能够根据特定的条件或需求选择不同的函数进行调用。这在设计可扩展和可重用的代码时非常有用。
1.3函数指针的使用
1.3.1定义
在C++中,可以通过以下两种方式定义函数指针:
1.使用typedef
关键字定义函数指针类型,然后使用该类型定义函数指针变量。例如:
typedef void (*FuncPtr)(int); // 定义函数指针类型
FuncPtr fnPtr; // 定义函数指针变量
2.直接使用函数指针的语法定义函数指针变量。例如:
void (*fnPtr)(int); // 定义函数指针变量
3.使用using关键字来定义。例如:
using FnPtr = void (*)(int); // 定义函数指针类型FnPtr
以上三种方式都定义了一个指向形参为int
类型,返回类型为void
的函数指针。
注:这里我们需要加上两个括号,它们表示fnPtr是一个函数指针变量,指向一个参数为int类型的函数。
1.3.2初始化
关于函数指针的初始化,我们可以直接赋值给一个已有函数的地址。例如:
void myFunction(int x) {// 函数体
}void (*fnPtr)(int); // 定义函数指针变量fnPtr = &myFunction; // 将myFunction函数的地址赋值给fnPtr
在C++中,可以使用取地址运算符&来获取函数的地址,也可以省略取址运算符直接赋值给函数指针变量。另外,使用using关键字定义的函数指针类型可以提高代码的可读性。
对了,在输出函数指针时需要注意,在C++中,函数指针的打印输出不会直接显示函数的地址,而是显示为1。因为C++中的函数指针是一种可调用类型,可以像函数一样进行调用,因此在进行输出时,函数指针会被隐式地转换为一个bool值,而非函数的内存地址。如果想要获得函数的地址,可以使用reinterpret_cast将函数指针转换为void*类型,然后进行打印输出。如下所示:
cout << reinterpret_cast<void*>(fnPtr) << endl; // 输出函数指针fnPtr所指向的函数的地址
这样,我们将得到正确的函数地址的输出。
接下来,我们就可以输出函数的地址了!如下:
1.3.2调用函数
我们可以通过函数指针直接调用相应的函数。例如,假设有一个函数指针fnPtr
,可以使用(*fnPtr)(参数列表)
的方式调用函数。
void myFunction(int x) {// 函数体
}int main() {void (*fnPtr)(int) = myFunction; // 定义函数指针并初始化// 调用函数(*fnPtr)(10);return 0;
}
1.3.3比较函数指针
我们可以使用函数指针进行比较操作,判断两个函数指针是否相等。函数指针相等表示两个函数指向同一个函数。
#include<bits/stdc++.h>
using namespace std;void myFunction1(int x) {// 函数体
}void myFunction2(int x) {// 函数体
}int main() {void (*fnPtr1)(int) = myFunction1; // 定义函数指针1并初始化void (*fnPtr2)(int) = myFunction2; // 定义函数指针2并初始化// 比较函数指针if (fnPtr1 == fnPtr2) {cout<<"ok"<<endl;} else {cout<<"no"<<endl;}cout << reinterpret_cast<void*>(fnPtr1) << endl;// 输出函数指针fnPtr所指向的函数的地址
cout << reinterpret_cast<void*>(fnPtr2) << endl; // 输出函数指针fnPtr所指向的函数的地址return 0;
}
结果:
1.4函数指针的练习
题目:编写一个程序,计算三角形的面积。利用函数指针来选择计算面积的方法。
步骤:
1. 声明一个函数指针,指向一个计算面积的函数。
2. 编写一个计算面积的函数,该函数接受三个参数表示三角形的边长,并返回计算得到的面积。
3. 编写第二个计算面积的函数,该函数接受两个参数表示三角形的底和高,并返回计算得到的面积。
4. 编写主函数,在其中通过用户输入选择计算面积的方法。
5. 在主函数中,根据用户选择的方法,使用函数指针调用相应的计算面积的函数,并输出结果。
知识点:
1. 函数指针的声明和使用。
2. 函数的定义和调用。
3. 三角形面积的计算方法。
三角形面积的计算方法有两种,一个是三边法,采用的是海伦公式,另一个是底高法,也就是公式面积=底*高/2。
流程图:
开始
声明函数指针
定义计算面积函数1
定义计算面积函数2
接收用户输入选择方法
根据选择使用函数指针调用相应函数
输出结果
结束
代码:
#include <iostream>using namespace std;// 声明函数指针
typedef double (*AreaFunc)(double, double);// 计算面积的函数1:三边法
double calcAreaBySide(double a, double b, double c) {double s = (a + b + c) / 2;return sqrt(s * (s - a) * (s - b) * (s - c));
}// 计算面积的函数2:底高法
double calcAreaByBaseHeight(double base, double height) {return 0.5 * base * height;
}int main() {int choice;double a, b, c, base, height;AreaFunc areaFunc;cout<<"选择方法:"<<endl;cin >> choice;switch (choice) {case 1:areaFunc = calcAreaBySide;cout << "三角形的三边长度:" << endl;cin >> a >> b >> c;cout << "三角形的面积为:" << areaFunc(a, b, c) << endl;break;case 2:areaFunc = calcAreaByBaseHeight;cout << "三角形的底和高:" << endl;cin >> base >> height;cout << "三角形的面积为:" << areaFunc(base, height) << endl;break;default:cout << "无效" << endl;break;}return 0;
}
本示例中,通过函数指针 AreaFunc 来选择使用不同的计算面积的函数。用户可以通过输入选择三边法或底高法来计算三角形的面积,程序会根据选择来调用相应的计算函数并输出结果。
2.函数指针数组
既然有函数指针,那肯定也有函数指针数组啦!函数指针数组是一个数组,每个成员都是一个函数指针。
2.1函数指针数组的作用
函数指针数组的作用主要有以下几个方面:
1. 调用不同的函数:函数指针数组可以存储多个函数的指针,通过数组的索引可以选择调用不同的函数。这样可以在运行时根据需要动态地选择不同的函数来执行特定的操作。
2. 函数回调:函数指针数组可以用于实现函数回调的机制。回调函数是指在特定的条件或事件发生时,通过函数指针来调用事先定义好的函数。通过函数指针数组,可以在需要的时候选择合适的回调函数进行调用。
3. 状态机:函数指针数组可以用于实现状态机的机制。状态机是一种表示状态和状态转换的模型,通过函数指针数组可以将每个状态定义为一个函数,使用数组索引进行状态转换。
4. 函数指针数组作为参数传递:函数指针数组可以作为参数传递给其他函数,以便在函数内部使用。这样可以将一组相关的函数作为整体传递,方便对这组函数进行统一的操作或处理。
总之,函数指针数组提供了一种灵活、动态和可扩展的方式来管理和调用函数,使得程序可以根据需要选择不同的函数进行执行,增强了程序的灵活性和可维护性。
2.2函数指针数组的使用
在C++中,函数指针数组的操作与C类似,但可以使用更具有面向对象特性的方式。
2.2.1 定义
使用typedef关键字可以简化函数指针类型的定义,使代码更具可读性。
typedef void (*FuncPtr)(int); // 定义函数指针类型FuncPtr func_ptr_array[N]; // 定义大小为N的函数指针数组
2.2.2 初始化
可以直接在定义函数指针数组时给出初始值,或通过循环赋值操作为数组元素赋予特定的函数指针。这里介绍在定义函数指针数组时给出初始值和数组元素赋予特定的函数指针这两种方法。
void func1(int);
void func2(int);FuncPtr func_ptr_array[] = {func1, func2}; // 初始化函数指针数组func_ptr_array[0] = func1; // 为函数指针数组赋值
func_ptr_array[1] = func2;
2.2.3 调用
这里我们可以使用数组的索引来选择并调用函数指针数组中的函数。
int index = 0;//索引
func_ptr_array[index](10); // 调用函数指针数组中索引为0的函数,并传入参数10
2.2.4 传参
这里同样可以将函数指针数组作为参数传递给其他函数,在函数内部使用。
void process_func_array(FuncPtr array[], int size) {//函数体......
}process_func_array(func_ptr_array, 2); // 将函数指针数组作为参数传递给函数
在C++中,可以使用函数指针数组来实现更加灵活的函数回调机制、策略模式等。此外,C++还提供了更强大的工具,如函数对象、Lambda表达式等,可以替代函数指针数组,在处理函数选择和回调方面更加方便和易用。
2.3函数指针二维数组
函数指针二维数组用于存储多个函数指针,每个函数指针可以指向一个函数。它的定义和使用方式与普通二维数组类似,只是数组元素是函数指针。
函数指针二维数组的定义如下:
typedef returnType (*functionName)(parameter1, parameter2, ...);functionName arrayName[rowSize][colSize];
其中,returnType
是函数的返回类型,functionName
是函数指针类型的名称,parameter1, parameter2, ...
是函数的参数列表。arrayName
是函数指针二维数组的名称,rowSize
是数组的行数,colSize
是数组的列数。
2.4函数指针数组的练习
题目:编写一个程序,根据输入的年份判断是否为闰年。
步骤:
1. 定义一个函数指针数组,用于存储判断闰年的函数地址。
2. 定义多个判断闰年的函数,如根据公历规则判断、根据儒略历规则判断等。
3. 在主函数中,输入一个年份。
4. 遍历函数指针数组,依次调用判断闰年的函数,并将输入的年份作为参数传递给该函数。
5. 根据函数的返回结果判断是否为闰年,如果是则输出“该年份是闰年”,否则输出“该年份不是闰年”。
知识点:
1. 函数指针数组的定义和使用。
2. 根据输入的年份调用对应的判断闰年函数。
3. 函数的参数传递和返回值。
流程图:
输入一个年份|
V
遍历函数指针数组|
V
调用判断闰年的函数,将年份作为参数传递|
V
根据返回结果判断是否为闰年|
V
输出结果
代码:
在运行时,程序会要求输入一个年份,然后遍历函数指针数组,依次调用判
#include <iostream>typedef bool (*leapYearChecker)(int); // 定义函数指针类型// 根据公历规则判断是否为闰年
bool isLeapYearByGregorian(int year) {if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {return true;} else {return false;}
}// 根据儒略历规则判断是否为闰年
bool isLeapYearByJulian(int year) {if (year % 4 == 0) {return true;} else {return false;}
}int main() {int year;std::cout << "请输入一个年份:";std::cin >> year;leapYearChecker leapYearCheckers[] = {isLeapYearByGregorian, isLeapYearByJulian}; // 函数指针数组int numCheckers = sizeof(leapYearCheckers) / sizeof(leapYearCheckers[0]); // 计算数组长度bool isLeapYear = false;for (int i = 0; i < numCheckers; i++) {isLeapYear = leapYearCheckers[i](year); // 调用判断闰年的函数if (isLeapYear) {std::cout << "该年份是闰年" << std::endl;break;}}if (!isLeapYear) {std::cout << "该年份不是闰年" << std::endl;}return 0;
}
断闰年的函数,并将输入的年份作为参数传递给该函数。根据函数的返回结果判断是否为闰年,并输出相应的结果。
3.回调函数与回调指针
回调函数(callback function)是指在某个函数执行完毕后自动调用的函数。它的作用是将一个函数传递给另一个函数,以便在适当的时候被调用。
3.1回调函数的用处
回调函数的作用主要体现在以下几个方面:
1.异步操作:通过传递回调函数作为参数,可以在某个操作完成后立即执行回调函数。这样可以避免阻塞主线程,提高程序的并发性和响应性。
2.事件处理:通过注册回调函数作为事件处理函数,可以实现对事件的响应和处理。这样可以增加程序的可扩展性和可维护性。
3.抽象接口:通过回调函数,可以将具体的实现逻辑与调用逻辑分离。这样可以提高代码的复用性和可读性。
总结而言,回调函数是一种常用的编程技术,可以实现异步操作、事件处理和抽象接口等功能。它可以提高程序的灵活性和可扩展性,使程序更加模块化和可维护。
3.2回调函数的使用
回调指针的使用包括以下几个步骤:
3.2.1 定义函数原型
首先需要定义回调函数的函数原型,包括返回类型和参数列表。这个函数原型将作为回调函数的类型,后续需要定义回调指针来指向这个函数。
// 定义回调函数的函数原型
typedef void (*CallbackFunction)(int);
3.2.2 声明变量
使用定义的回调函数类型来声明回调指针变量。回调指针变量是一个指向回调函数的指针,可以用来存储回调函数的地址。
// 声明回调指针变量
CallbackFunction callbackPointer;
3.2.3定义
根据之前定义的函数原型,实现回调函数的具体逻辑。回调函数可以在特定事件或条件发生时被调用执行,可以在函数内部进行相应的操作。
// 回调函数
void callbackFunction(int value) {std::cout << "Callback Function: " << value << std::endl;
}// 需要回调的函数
void doSomething(int value, CallbackFunction callback) {std::cout << "Doing something with value: " << value << std::endl;// 调用回调函数callback(value);
}
3.2.4 地址传递
在需要使用回调函数的地方,将回调函数的地址作为参数传递给其他函数。这些函数在特定的时候可以通过回调指针调用回调函数。
// 将回调函数的地址传递给其他函数callbackPointer = callbackFunction;
3.2.5调用
在需要触发回调函数的时候,通过回调指针调用回调函数。回调函数将执行其内部的逻辑操作,并返回结果或执行特定的任务。
// 调用需要回调的函数doSomething(10, callbackPointer);
3.3回调指针
回调指针(callback pointer)是指一个指针,它指向回调函数的内存地址。通过使用回调指针,可以在适当的时候调用回调函数。
3.3.1回调指针的使用
在C++中,可以通过回调指针在回调函数中调用特定的函数或方法。下面是一个代码示例:
#include <iostream>// 回调函数的定义
void callbackFunc(int arg) {std::cout << "Callback called with argument: " << arg << std::endl;
}// 接受回调函数指针的函数
void doSomething(int data, void (*callback)(int)) {// 执行其他操作std::cout << "Doing something with data: " << data << std::endl;// 调用回调函数callback(data);// 执行其他操作
}int main() {int data = 42;// 调用doSomething函数,并传递回调函数指针doSomething(data, callbackFunc);return 0;
}
在这个例子中,callbackFunc是一个回调函数,它接受一个整数参数,并在函数内部打印该参数的值。doSomething函数接受一个整数参数和一个指向回调函数的指针。它在执行其他操作后调用回调函数,将传入的数据作为参数传递给回调函数。
在main函数中,首先定义了一个整数变量data,然后调用doSomething函数,并将data和callbackFunc作为参数传递给它。
当doSomething函数执行时,它会执行一些操作,然后调用传入的回调函数指针,传递给它data`作为参数。这样,回调函数callbackFunc将被调用,并打印出传入的参数值。
通过回调指针,可以在回调函数中灵活地调用不同的函数或方法,实现不同的功能和逻辑。
3.3.2回调函数与回调指针的关系
回调函数与回调指针之间存在着紧密的关系。下面是一个简单的图表,用于说明它们之间的关系:
+---------------------+| 调用者函数 |+---------------------+|| 回调指针|+---------------------+| 回调函数 |+---------------------+
解析:在这个图表中,调用者函数是一个函数,它需要在特定的事件或条件发生时执行某些操作。为了实现这个功能,调用者函数会定义一个回调指针,并将需要执行的回调函数的地址赋给这个指针。
回调函数是一个独立的函数,它执行实际的操作。它的原型(参数列表和返回值类型)需要与回调指针指向的函数类型相匹配。当特定事件或条件发生时,调用者函数将使用回调指针调用回调函数,从而执行所需的操作。
通过使用回调指针,调用者函数可以在运行时灵活地指定要执行的回调函数。这使得回调函数的执行可以根据具体的需求动态地确定。
总结:回调函数通过回调指针与调用者函数建立联系,实现在特定事件或条件下执行指定操作的机制,相当于“过渡”的作用。回调指针允许在运行时动态地指定回调函数,从而实现灵活性和可扩展性。
4.指针函数
指针函数是指返回指针的函数。与普通函数返回基本数据类型或对象不同,指针函数返回一个指针,该指针指向内存中的某个地址。
4.1指针函数的作用
指针函数的作用主要有以下几个方面:
1.返回动态分配的内存:指针函数可以用于动态分配内存,并返回指向该内存的指针。这样可以在函数外部使用这些动态分配的内存,并在适当的时候释放。
2.返回局部变量的地址:指针函数可以返回局部变量的地址。虽然局部变量的作用域只限于函数内部,但通过返回指针,可以在函数外部访问并修改局部变量的值。
3.返回数组、链表等数据结构:指针函数可以返回数组、链表等数据结构的指针,这样可以在函数外部通过指针访问和操作这些数据结构。
4.函数指针的使用:指针函数可以返回函数指针,即返回一个指向函数的指针。这样可以在函数外部调用不同的函数,实现程序的动态性。
4.2指针函数的操作
指针函数是一种返回指针的函数。它可以用来返回动态分配的内存、对象的指针或者函数指针。
下面是一些关于指针函数的常见操作:
4.2.1 声明
int* myFunction(); // 返回int类型指针的指针函数
上述代码声明了一个返回int类型指针的指针函数myFunction。
4.2.2 定义
int* myFunction() {int* ptr = new int(10);return ptr;
}
上述代码定义了一个指针函数myFunction,它动态分配了一个int类型的内存,并返回指向该内存的指针。
4.2.3 调用
int* result = myFunction();
上述代码调用指针函数myFunction,并将返回的指针存储在result变量中。
4.2.4返回
cout << *result << endl; // 输出指针所指向的值
delete result; // 释放动态分配的内存
上述代码使用指针函数返回的指针,输出指针所指向的值,并释放动态分配的内存。
4.3指针函数的练习
题目:编写一个指针函数,接受一个整数数组和数组的长度作为参数,返回一个指向数组中最大元素的指针。
步骤:
1. 声明并定义一个指针函数,函数名为`findMax()`,参数为整数数组和数组的长度。
2. 在函数内部,声明一个指针变量`max`,并将其初始化为指向数组的第一个元素。
3. 使用一个循环遍历数组的每个元素:
- 如果当前元素大于`max`指向的值,则将`max`指向当前元素。
4. 返回指针`max`。
知识点:
- 指针函数的声明和定义
- 指针的初始化和赋值
- 指针的比较
流程图:
开始
|
声明并定义指针函数 findMax(arr, length)
|
声明并初始化指针变量 max = arr
|
循环遍历数组的每个元素
|
| 如果当前元素 > *max
| |
| 将 max 指向当前元素
|
返回 max
|
结束
代码:
int* findMax(int* arr, int length) {int* max = arr;for (int i = 0; i < length; i++) {if (arr[i] > *max) {max = &arr[i];}}return max;
}
接下来,我们就可以在main函数里直接调用这个函数啦!这个练习可以帮助你熟悉指针函数的声明、定义和使用,以及指针的操作。可以通过测试不同的数组来验证函数的正确性。记得在使用完动态分配的内存后,及时释放它们,以避免内存泄漏。
总结
本篇博客到这里就结束了,感谢大家的支持与观看,如果有好的建议欢迎留言,制作不易,如果对您有帮助,那请给PingdiGuo_guo一个免费的赞,谢谢啦!
相关文章:
C++指针(四)万字图文详解!
个人主页:PingdiGuo_guo 收录专栏:C干货专栏 前言 相关文章:C指针(一)、C指针(二)、C指针(三) 本篇博客是介绍函数指针、函数指针数组、回调函数、指针函数的。 点赞破六…...
【AI提示词】长期主义助手提供规划支持
提示说明 长期主义是一种关注长期利益和持续学习的思维模式,帮助个人和组织在快速变化的环境中保持耐心和系统性思考。 提示词 # Role: Long-termist Assistant## Profile - language: 中文 - description: 长期主义是一种关注长期利益和持续学习的思维模式&…...
JavaScript逆向工程:如何判断对称加密与非对称加密
在现代Web应用安全分析中,加密算法的识别是JavaScript逆向工程的关键环节。本文将详细介绍如何在逆向工程中判断JavaScript代码使用的是对称加密还是非对称加密。 一、加密算法基础概念 1. 对称加密 (Symmetric Encryption) 特点:加密和解密使用相同的…...
制造企业如何通过实现数据统一?
随着生产规模的扩大、供应链的复杂化以及市场需求的快速变化,企业内部的数据管理问题日益凸显。数据孤岛、数据冗余、数据不一致等问题不仅降低了运营效率,还可能导致决策失误。那么,制造企业如何才能打破这些壁垒,实现数据的统一…...
ICRA-2025 | 视觉预测助力机器人自主导航!NavigateDiff:视觉引导的零样本导航助理
论文:Yiran Qin 1 , 2 ^{1,2} 1,2, Ao Sun 2 ^{2} 2, Yuze Hong 2 ^{2} 2, Benyou Wang 2 ^{2} 2, Ruimao Zhang 1 ^{1} 1单位: 1 ^{1} 1中山大学, 2 ^{2} 2香港中文大学深圳校区论文标题:NavigateDiff: Visual Predictors are Ze…...
Java 与 LibreOffice 集成开发指南
1. 引言 Java 与 LibreOffice 的集成开发为开发者提供了一种强大的工具,用于实现文档自动化处理、文档转换、内容编辑等任务。通过 Java 调用 LibreOffice 提供的 API,可以实现跨平台的文档处理功能,满足各种业务需求。本文将详细介绍如何使…...
如果单表数据量大,只能考虑分库分表吗
程序员最怕啥?不是需求改八遍,也不是半夜报警电话,而是数据库突然卡成PPT!尤其是当单表数据冲到几千万行,查询慢得像老牛拉车,这时候团队第一反应往往是:“赶紧分库分表!” 但兄弟,分库分表可不是什么温柔小姐姐,它更像是个浑身带刺的仙人掌——你以为抱上就能解决问…...
3.3.1 spdlog异步日志
文章目录 3.3.1 spdlog异步日志1. spdlog1. 日志作用2 .同步日志和异步日志区别 2. spdlog是什么下载命令:2. spdlog为什么高效3. spdlog特征5. spdlog输出控制6. 处理流程7. 文件io8.问题 2. 如何创建logger3. 如何创建sink4. 如何自定义格式化5. 如何创建异步日志…...
【Web功能测试】注册与登录功能测试用例设计深度解析
1 注册功能测试用例设计 1.1 明确需求与测试范围 必填字段:手机号、验证码、密码 手机号规则:11位手机号 密码规则:6-16位,需包含大小写字母必须同时存在,数字或符号存在其一 协议勾选 提交后跳转登录页或显示成功…...
netstat 查看端口占用、杀死进程
文章目录 查看端口占用强制杀死 报错信息使用 lsof 查看端口占用 netstat -tanlp强制杀死 在安全的情况下,用下面命令杀死端口占用的进程 sudo kill $(sudo lsof -t -i:3128)报错信息 部署程序时,会出现这样的报错: Error response from…...
Windows 11 PowerShell重定向文本文件的编码问题
目录 问题的由来 编码导致的问题 解决办法 VSCode进行转换 记事本进行转换 直接指定输出的文本编码 总结 问题的由来 在我的嵌入式系统的课程中有一个裸机开发的实验,其中需要把图片等文件转换为C语言数组保存在程序中。课程中,我推荐了CodePlea的…...
蓝桥杯冲刺:一维差分
系列文章目录 蓝桥杯系列:一维差分 文章目录 系列文章目录前言一、一维差分: 差分数组的意义: 二、差分的性质: 差分和前缀和的关系 三、一维差分代码实现:四、典型真题(利用一维差分来实现) 这…...
理解企业内部信息集成
目录 1. 技术平台集成 2. 数据集成 3. 应用集成 4. 业务过程集成 5. 应用集成与企业内部信息集成的区别 企业内部信息集成是将分散的技术、数据、应用和业务流程整合为一个协同的整体,以提高效率、减少冗余和增强决策能力。 企业内部信息集成一般可以分为4个方…...
论文学习:《利用图注意力网络增强单细胞多组学数据的整合》
原文标题:Enhanced Integration ofSingle-Cell Multi-Omics Data Using Graph Attention Networks 原文链接:https://pubs.acs.org/doi/abs/10.1021/acssynbio.4c00864 跨不同组学层的数据集成面临的挑战:高维度、异质性和稀疏性。 变分自编码…...
HumanDil-Ox-LDL:保存:2-8℃保存,避免强光直射,不可冻存
化学试剂的基本介绍: /// 英文名称:HumanDil-Oxidized LowDensityLipoprotein /// 中文名称:人源红色荧光标记氧化型低密度脂蛋白 /// 浓度:1.0-4.0 mg/ml /// 外观:乳状液体 /// 缓冲液组分:PBS&…...
基于3d相机的点云物体检测与路径规划
🧩 代码结构和解释: 点云预处理 (preprocess_point_cloud): 使用 Voxel 下采样 来减少点云数据量,去除不必要的噪声。 使用 统计滤波器 去除离群点,以提高后续拟合的精度。 V型焊缝路径拟合 (fit_weld_path_v)&…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(2):んです
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(2):んです 1、前言(1)情况说明(2)工程师的信仰2、知识点(1)~んです & ~の(2)意味(いみ)&形(かたち)&使い方(つかいかた)(3)そうなんですか & そうなんだ。(4)何をしているんですか & 何を…...
yolov8在windows系统的C++版本的onnxruntime部署方法
1.各个软件的的环境需要保持在统一的版本。 onnxruntime需要和cuda的版本对应上,版本号:onnxruntime-win-x64-gpu-1.18.1 ,链接: NVIDIA - CUDA | onnxruntime cuda:本机显卡支持的版本,cuda11.7,链接:CUDA Toolkit Archive | NVIDIA Developer cudnn:需要对应到cud…...
AD软件的系统设置
设置 1.自动保存(DATA -> backup) 2.原理图-复制元器件递增位号 3.原理图-用斜线表示负信号 4.PCB-选择移动重叠的元器件 5.PCB-十字光标全屏大小 6.PCB-选择部分连接网络的走线全亮/显示多个网络的颜色(TP) 7.PCB-DRC报错的图…...
算法---子序列[动态规划解决](最长递增子序列)
最长递增子序列 说白了,要用到双层循环! 用双层循环中的dp[i] class Solution { public:int lengthOfLIS(vector<int>& nums) {vector<int> dp(nums.size(),1);for(int i 0;i<nums.size();i){for(int j0;j<i;j){if(nums[i]>num…...
快速幂(模板)
快速幂 取余运算性质:(a*b*c)%d (a%d * b%d * c%d)%d ; #include <iostream> using namespace std; int main() {long long b,p,k;//b(底数)p(指数)k(取模数)cin>>b>>p>>k;long long ret1;b%k;//防止底数过大//模版,记…...
蓝桥杯 好数【暴力、基础知识】
题目: AC代码: #include<bits/stdc.h> using namespace std; int ans0; int n; bool check(int x){int cnt1;while(x!0){int tx%10;if(cnt%21){ if(t%20) return false; //奇数位置是偶数} if(cnt%20){if(t%21) return false; //偶数位是奇数}cnt…...
【Kubernetes】Kubernetes中如何实现灰度发布
Kubernetes中实现灰度发布 一、基于Ingress-nginx的流量切分(适用中小规模) 权重分流 在Ingress资源中通过nginx.ingress.kubernetes.io/canary-weight注解设置新版本流量比例apiVersion: networking.k8s.io/v1 kind: Ingress metadata:annotations:ng…...
【Reinforcement Learning For Quadruped Control】1
强化学习(RL)是一种机器学习范式,代理通过与环境的互动来学习做出决策。强化学习的核心概念围绕以下几个方面展开:a) 代理agent,做出决策;b) 环境environment,响应代理的决策;c) 状态…...
工程企业如何实现四算联动?预算-核算-决算系统解析
在工程行业,项目管理的高效性直接决定了企业的盈利能力和市场竞争力。尤其是在EPC(工程总承包)模式下,工程企业面临着复杂的业务场景和多维度的成本管控需求。如何通过“四算联动”(概算、预算、核算、决算)…...
【SpringBoot】处理actuator风险漏洞
最近给系统做渗透测试,扫描出了一个actuator风险漏洞,属于高危级别,通过actuator接口可以拿到用户敏感信息。这个问题处理起来倒也简单,禁用actuator或者限制访问就可以了 # 禁用actuator接口配置 management:server:port: -1# 限…...
MACOS15版本安装 python mysqlclient 以连接mysql 8.0
MACOS14/15 版本安装 python mysqlclient 以连接mysql 8.0 主要用于macos django4 mysql8.0 开发项目 准备材料 macos > 13.0 python > 3.10.0 (不强制) mysql > 8.0 安装步骤 安装 brew 使用国内源安装brew /bin/zsh -c "$(curl -f…...
KV Cache大模型推理加速功能
KV Cache KV Cache是大模型标配的推理加速功能,也是推理过程中,显存资源巨大开销的元凶之一。在模型推理时,KV Cache在显存占用量可达30%以上。 目前大部分针对KV Cache的优化工作,主要集中在工程上。比如著名的VLLM,…...
Windows下安装WSL2下的Ubuntu、docker容器的IP地址(上)
既然容器支持多个应用,那么容易想到应该有对应的ip地址和端口,这样才能和Ubuntu主机进行通讯,ubuntu访问外网也应该有ip能连接到外网才行,要搞清楚这些ip地址的关系才行。 前面两篇文章中说了怎么实现windows和wsl2下的ubuntu的文…...
vue实现中英文切换
第一步:安装插件vue-i18n,npm install vue-i18n 第二步:在src下新建locales文件夹,并在locales下新建index.js、EN.js、CN.js文件 第三步:在EN.js和CN.js文件下配置你想要的字段,例如: //CN.js…...
探索 Vue 3 中 vue-router 的 router.resolve () API
一、router.resolve() 是什么 router.resolve() 就好比是一个精准的 “导航参谋”。当我们在 Vue 3 应用里需要明确某个路由地址对应的详细信息时,它就能派上用场。我们给它传入路由信息,像路径、参数等,它会解析出对应的路由对象࿰…...
Excel 插件推荐:提升Excel能力的效率神器!
一、Excel玩家的觉醒时刻 在财务部的深夜加班现场,李师傅的咖啡杯上凝结着第3圈水渍。眼前的Excel窗口堆叠如俄罗斯方块:重复值删除进度15%、VLOOKUP公式报错3处、合并单元格序号乱成毛线团…这场景是否也戳中了你的痛点? 每个Excel高手都经…...
leetcode_383. 赎金信_java
383. 赎金信https://leetcode.cn/problems/ransom-note/ 1、题目 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。 magazine 中的每个字…...
应用安全系列之四十五:日志伪造(Log_Forging)之三
1、简介 针对Java的日志系统有多种,本文主要描述如何通过修改配置文件来解决logback和log4j的日志伪造问题。 2、logback 2.1、系统提供的解决方案 在logback.xml中配置编码器自动转义特殊字符: 复制 <configuration><appender name"C…...
FTPClient开发遇到的坑
1. 生成文件夹乱序 这里用分隔符把路径划分开,意在一层一层创建目录 这里可能会出现乱序 正确的代码 先换一下分隔符 再一次生成所有路径 2.ftpClient 需要指定被动模式才能绕开端口限制 有些 服务器没有打开指定端口,上传文件会出现 425 Canno…...
leetcode0155. 最小栈-medium
1 题目:最小栈 官方标定难度:中 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。 void push(int val) 将元素val推入堆栈。 void pop() 删…...
操作系统 3.6-内存换出
换出算法总览 页面置换算法 FIFO(先进先出): 最简单的页面置换算法,淘汰最早进入内存的页面。 优点:实现简单。 缺点:可能会导致Belady异常,即增加内存反而降低性能。如果刚换入的页面马上又要…...
Python中的数值运算函数及math库详解
文章目录 Python中的数值运算函数及math库详解一、内置数值运算函数1. 基本数值运算函数2. 类型转换函数3. 进制转换函数 二、math库中的数学常数三、math库常用数学函数1. 数论与表示函数2. 幂函数与对数函数3. 三角函数4. 角度转换5. 双曲函数6. 特殊函数 四、实际应用示例1.…...
安卓开发提示Android Gradle plugin错误
The project is using an incompatible version (AGP 8.9.1) of the Android Gradle plugin. Latest supported version is AGP 8.8.0-alpha05 See Android Studio & AGP compatibility options. 改模块级 build.gradle(如果有独立配置):…...
《Uniapp-Vue 3-TS 实战开发》一键授权登录
在使用 UniApp 结合 Vue 3 和 TypeScript 开发时,实现一键授权登录功能通常涉及到调用微信小程序的授权接口(如 wx.getUserProfile 或 wx.login)来获取用户信息和登录凭证,然后将这些信息发送到后端进行验证和处理。以下是一个完整的实现示例,展示如何在 UniApp 中实现一键…...
Windows 图形显示驱动开发-WDDM 1.2功能_WDDM 1.2 和 Windows 8
简介 WDDM 是随 Windows Vista 一起引入的,以取代 Windows XP 或 Windows 2000 显示驱动程序模型 (XDDM) 。 随着 Windows Vista 中的引入,WDDM 体系结构提供了启用新功能的功能,例如桌面组合、增强的容错、视频内存管理器、GPU 计划程序、D…...
155.最小栈
1.题目解析 题目是让我们设计一个栈,它于STL库中栈的区别是支持检索到了最小元素的栈但是需要时间复杂度为常数,我们很容易想到的是记录最小值。但是如果中途删除的话最小值可能失效,所以我们选择用2个栈来实现。 2.算法原理 我们创建2个栈…...
[C语言笔记]10、字符串
前言: C语言的相关知识点的笔记均在下面的专栏链接中,欢迎订阅! c语言笔记_1zero10的博客-CSDN博客 10-1字符数组与字符串 1、字符数组就是一个数组,数组的每一个元素都是一个字符 首先利用字符数组,回顾以前学过…...
Windows系统备份和还原点
一、简介 系统的还原点存储了当前系统的主要状态,包括一些关键的配置信息和参数(包括注册表、系统服务设置、设备驱动程序设置等)。将此时的状态进行备份,在系统发生故障时,可以还原到此还原点的状态中,这…...
内联汇编知识点earlyclobber=
arm64内联汇编格式: asm volatile ("汇编指令1\n\t""汇编指令2\n\t""汇编指令3": 输出操作数列表: 输入操作数列表: 可能被修改的寄存器列表 );示例1:简单的寄存器操作 uint64_t add_numbers(uint64_t a, uint64_t b) {…...
修改ESP32CAM的示例CameraWebServer里的camera_index.h的方法
在这里,默认你已经会使用Arduino IDE或者PlatformIO通过烧录底座对ESP32CAM(如下图)进行烧录,并能通过浏览器对其进行访问。 我们访问到下图的界面时,不禁有个疑问,这个界面是如何生成的,如果我…...
Python学习笔记(二)(字符串)
文章目录 编写简单的程序一、标识符 (Identifiers)及关键字命名规则:命名惯例:关键字 二、变量与赋值 (Variables & Assignment)变量定义:多重赋值:变量交换:(很方便哟) 三、输入与输出 (In…...
ViewModel vs AndroidViewModel:核心区别与使用场景详解
在 Android 的 MVVM 架构中,ViewModel 和 AndroidViewModel 都是用于管理 UI 相关数据的组件,但二者有一些关键区别: 1. ViewModel 基本用途:用于存储和管理与 UI 相关的数据,生命周期与 Activity/Fragment 解耦&…...
Windows环境下 全屏显示某个字符串
case WM_PAINT: {PAINTSTRUCT ps;HDC hdc BeginPaint(hWnd, &ps);// 获取完整客户区尺寸RECT rc;GetClientRect(hWnd, &rc);// 全屏时:整个窗口作为显示区域RECT displayRect rc;// 纯黑背景FillRect(hdc, &displayRect, (HBRUSH) GetStockObject(BLA…...
禅道MCP Server开发实践与功能全解析
一、简介 1、MCP Server核心定义 MCP Server(Meta Command Protocol Server)是一种基于客户端-服务器架构的轻量级服务程序,采用统一的mcp协议格式,通过连接多样化数据源和工具为AI应用提供扩展能力。它作为中间层,实…...