C语言---深入指针(4)
回调函数
//回调函数就是通过函数指针调用的函数
//这个在之前的转移表-计算器里面很明显,通过函数指针数组内的函数指针进行函数的调用
//
//
// 将这四段代码分装成一个函数,一个代码将这4个问题都解决
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mull(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
void menu()
{printf("**************************************\n");printf("********** 1.add 2.sub***********\n");printf("********* 3.mull 4.div***********\n");printf("********* 0.exit *************\n");printf("**************************************\n");
}
void Calc(int (*pf)(int, int))//因为传过来的是函数的地址,那么就要用函数指针进行接收
{int x = 0, y = 0,ret=0;printf("请输入两个操作数");scanf("%d %d", &x, &y);ret = pf(x, y);//当pf接收到的是加法函数的地址的时候,我们直接用pf来调用//对于函数名就是函数的地址,用指针变量存起来的就是函数地址,那么指针变量的名字就是函数变量的地址//那么可以直接用指针变量的名字进行调用printf("%d\n", ret);
}
int main()
{int ret = 0;int input = 0;int x = 0, y = 0;do{menu();//菜单printf("请选择:");scanf("%d", &input);switch (input){case 1:Calc(Add); //将加法函数的地址传过去--函数名是地址 break;case 2:Calc(Sub); break;case 3:Calc(Mull); break;case 4:Calc(Div);break;case 0:printf("退出计算器\n");break;default:printf("选择错误,重新选择\n");break;}} while (input);return 0;
}//这4个代码的差异就是运算的方式不同
//
// Calc是中间商,Add这些计算的函数是回调函数
//
// 通过函数调用另一个函数进行调用
//
//当你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其
//所指向的函数时,被调用的函数就是回调函数
//这个代码里面回调函数就是Add,Sub,Mull,Div
回忆冒泡函数
//回忆冒泡排序---对一组整数进行排序
//void bubble_sort(int arr[], int sz)//接受一个整型数组
//{
// //趟数
// for (int i = 0; i < sz-1; i++)
// {
// //一趟内部的两两比较
// for (int j = 0; j < sz - 1 - i; j++)
// {
// if (arr[j] > arr[j + 1])
// {
// int tmp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = tmp;
// }
// }
// }
//}
//print(int arr[], int sz)
//{
// for (int i = 0; i < sz; i++)
// {
// printf("%d ", arr[i]);
// }
//}
//int main()
//{
// int arr[] = { 3,1,7,9,4,2,6,8,0 };
// //进行排序--升序
// int sz = sizeof(arr) / sizeof(arr[0]);
//
// //冒泡排序核心思想,两两数字进行比较,不满足我们要求的顺序的话我们可以对其进行交换
// //满足我们要求的顺序的话我们就换下一对数字进行比较
//
// //冒泡排序进行排序
// bubble_sort(arr,sz);
// print(arr,sz);
// return 0;
//}
//对于冒泡排序的话,只能排序整型数组
//对于其他类型的数组无法排序
//字符串数组、字符数组、结构体数组、浮点数数组
strcmp----字符串的大小比较
/字符串的比较
//应该使用strcmp进行比较
//int strcmp(const char* str1, const char* str2);
//char str1[]="Hello";
//char str2[]="hello";
//strcmp(str1, str2));
// 如果 strcmp 返回值大于 0,
// 则表示第一个字符串(str1)在比较中大于第二个字符串(str2)。
//
a,b,c,d,c,e,f
a,b,c,q
因为d的ASCII小于q的,所以第一行的字符串就小于第二行的字符串
strcmp比较的不是长度,比较的是对应位置的字符ASCII大小的
qsort的结构
而接下来介绍的qsort能适用于任意类型的数据的排序
void qsort(void* base,//指向待排序数组第一个元素的指针size_t num, //base指向的数组中的元素个数size_t size, //base指向的数组中每个元素的大小int(*com)(const void*, const void*)//函数指针--传递函数的地址//);
利用qsprt进行整型数组的排序
//对于冒泡排序比较不同的类型的数据时,两个循环没有什么差异,但是对于不同的数据进行比较就有着差异
//对于整数是进行比较大小,但是并不是所有的数据能能用比'>''<'进行比较//既然不同数据的元素比较是有差异的,那么就直接把两个元素比较的代码抽离出来
//谁要调用qsort来进行比较排序,那就让谁提供比较的函数//下面的函数比较的是p1指向的元素和p2指向的元素
//对函数
//p1指向的元素比p2指向的元素小的时候,返回的是小于0的数
//p1指向的元素等于p2指向的元素的时候,返回的是0
//p1指向的元素比p2指向的元素打的时候,返回的是大于0的数//咱么为了使用qsort函数,我们必须提供一个比较2个整型的比较函数
//格式int cmp_int(const void*p1, const void*p2),那么这个函数的名字就是qsort函数的第四个条件
//int cmp_int(const void*p1, const void*p2)
//{
// //p1就指向了这个数组里面的3,p2指向的就是1
// /*if(*p1>*p2)*///不能这么写,因为在函数的参数里面,p1的类型是void*,p2是void*
// //void *指针不能进行解引用操作
// //将p1的类型强制转换成int*,再进行解引用就行了 *(int*)p1
// //比较的三种情况
// if (*(int*)p1 > *(int*)p2)
// {
// return 1;
// }
// else if (*(int*)p1 < *(int*)p2)
// {
// return -1;
// }
// else
// {
// return 0;
// }
//
//}
//void print(int arr[], int sz)
//{
// for (int i = 0; i < sz; i++)
// {
// printf("%d ", arr[i]);
// }
//}
test这个函数测试qsort来排序整型数据
//void test1()
//{
// int arr[] = { 3,1,7,9,4,2,6,8,0 };
// int sz = sizeof(arr) / sizeof(arr[0]);
// qsort(arr, sz, sizeof(arr[0]), cmp_int);
// //(数组首元素地址,数组长度,每个元素字节大小,进行比较大小的函数)
// print(arr, sz);//打印排序完后的数组
//}
//int main()
//{
// test1();
// return 0;
//}//提供想要排序的数组,计算数组元素个数
//再利用qsort进行排序
//再利用qsort进行排序的时候,要提供数组首元素的地址、数组长度、数组每个元素的字节大小、
//最后再提供一个比较的函数的函数名,这个函数有固定的写法
//int cmp_int(const void*p1, const void*p2)
//因为p1和p2的类型都是void*,不能对其进行解引用进行比较,
//所以我们必须将其强制类型转换,(int*)p1
//再对其进行解引用*(int*)p1
//再将*(int*)p1与*(int*)p2进行比较
//前者大于后者就返回大于0的数
//前者小于后者就返回小于0的数
//前者等于后者就返回0//对于qsort函数来说,我们只需要额外构建一个比较函数就能利用qsort进行快速排列
对于qsort函数来说,我们只需要额外构建一个比较函数就能利用qsort进行快速排列
//对下面代码进行简化
// test1
int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}
//因为这里比较的是整数,那么我们直接作差返回
void print(int arr[], int sz)
{for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}
}
//test这个函数测试qsort来排序整型数据
void test1()
{int arr[] = { 3,1,7,9,4,2,6,8,0 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_int);//(数组首元素地址,数组长度,每个元素字节大小,进行比较大小的函数)print(arr, sz);//打印排序完后的数组
}
int main()
{test1();return 0;
}
利用qsprt进行结构体的排序
/*void qsort(void* base,//指向待排序数组第一个元素的指针size_t num, //base指向的数组中的元素个数size_t size, //base指向的数组中每个元素的大小int(*com)(const void*, const void*)//函数指针--传递函数的地址//);*/
//利用qsort函数对结构体进行排序
struct Stu//创建一个结构体
{char name[20];int age;
};//按照名字比较两个结构体的数据
int cmp_stu_by_name(const void* p1, const void* p2)//p1和p2分别指向数组中的结构体
{//先将p1强制类型转换//(struct Stu*)p1---结构体指针-----不能直接指向成员 错误写法:(struct Stu*)p1->//要先括起来,将强制类型转换后的结构阔起来,才能找到成员//((struct Stu*)p1)->name, ((struct Stu*)p2)->name// //两个名字是字符串,字符串比较是采用strcmp函数的return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);//因为strcmp函数的返回值和我们期望的qsort的第四个比较函数的返回值一样的,//所以我们直接将strcmp的值返回//strcmp要包含头文件的include <string.h>
}
void print(struct Stu arr[], int sz)
{for (int i = 0; i < sz; i++){printf("%s ", arr[i].name);}
}
void test2()
{struct Stu arr[] = { {"zhangsan",20},{"lisi",35},{"wangwu",18}};//给了三个人的信息 //利用qsort对数组内的信息进行排序int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);//传递的函数是进行比较两个结构体对象//但是我们现在是按照名字比较还是年龄比较呢?print(arr, sz);
}int main()
{test2();return 0;
}
//按照年龄排序
struct Stu//创建一个结构体
{char name[20];int age;
};
void print(struct Stu arr[], int sz)
{for (int i = 0; i < sz; i++){printf("%d ", arr[i].age);}
}//打印结果:18 20 35
void cmp_stu_by_age(const void* p1, const void* p2)
{//return strcmp(((struct Stu*)p1)->age, ((struct Stu*)p2)->age);//因为age是两个整数,所以不需要用strcmp了return ((struct Stu*)p1)->age-((struct Stu*)p2)->age;//将他们的值进行大小比较,直接返回//前者大于后者直接返回大于0的数//前者小于后者直接返回小于0的数//前者等于后者直接返回0}
void test3()
{struct Stu arr[] = { {"zhangsan",20},{"lisi",35},{"wangwu",18} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);print(arr, sz);}
int main()
{test3();return 0;
}
关于结构体的补充知识点
利用结构体指针来访问结构体里面的成员对象
//结构体知识点补充,利用结构体指针来找到结构体里面的数据
struct Stu//创建一个结构体
{char name[20];int age;
};
int main()
{struct Stu s = { "zhangsan",20 };//第一种写法:printf("%s %d\n", s.name, s.age);//这里的知识点就是利用结构体名字加点再加结构体对象,就可以调用出对应的数struct Stu* ps=&s;//将变量s的地址取出存放到结构体指针内//struct Stu*就是这个结构体指针ps的类型//ps里面存放的是s的地址,ps就指向了s//第二种写法://那么我们利用ps来找到这个结构体数组里面的数据怎么找呢?printf("%s %d\n", (*ps).name, (*ps).age);
//ps是里面存放的是这个结构体的地址,对ps进行解引用得到的就是这个结构体s了//第三种写法:printf("%s %d\n", ps->name, ps->age);//ps指向的对象的成员return 0;
}
//结构体成员访问操作符
// . 结构体变量.成员名
//-> 结构体指针->成员名
qsort函数的总结
对于qsort函数来说
主要的就是括号内的第四个元素,也就是进行元素比较的函数的名字
对于qsort来说,这个进行比较的函数只需要返回三种值
大于0,小于0,或者等于0,只要传递回来就能直接快速排列
对于qsort函数来说:
第一个元素是要排列的数组的首元素的地址,就是数组名
第二个元素就是这个数组的元素个数sz
第三个元素就是每个元素的字节大小sizeof([0])
第四个元素就是这个比较的函数的函数名
对于这个比较函数就有说法了
这个就是固定格式
返回值是数字,就是大于0的数,0,小于0的数,所以函数前面是int
int cmp_int(const void* p1, const void* p2)
p1和p2的类型都是void*
p1和p2都指向的数组内的要进行比较的元素
如果要进行比较的话就需要对这个指针进行强制类型转换
假设:
int*强制类型转换,
(int*)p1
再对转换后的结果进行解引用就是p1指向的那个数
(int)p1
判断的是整型数组的话:
那么我们直接写:return* (int*)p1 - *(int*)p2;
两个数进行相减,返回值三种情况:大于0的数、0、小于0的数
假如说要判断结构体成员的年龄的话
return ((struct Stu)p1)->age-((struct Stu)p2)->age;
返回的就是年龄相减的值
先强制类型转换p1
(struct Stu*)p1
因为p1指向的是这个结构体数组,那么我们直接通过箭头操作符直接访问数据
(struct Stu*)p1→age
假如说要判断结构体成员的姓名的话
对于这个结构体数组来说,这个姓名就是字符串
对于字符串的比较我们要用到strcmp函数
因为我们想要的这个比较函数的返回值和这个strcmp的返回值一样的,那么我们直接返回strcm函数的值
return strcmp(((struct Stu)p1)->name, ((struct Stu)p2)->name);
strcmp(((struct Stu)p1)->name, ((struct Stu)p2)->name)
在strcmp函数中进行比较的是((struct Stu)p1)->name和((struct Stu)p2)->name
qsort实现升序和降序的原理
因为qsort默认实现的是升序
对于数组的快排,如果我们想实现数组的降序,
因为qsort是固定死的
但是qsort里面的一个元素,第四个元素,比较函数
我们只能通过这个比较函数来实现降序
对于这个代码
return ((struct Stu)p1)->age-((struct Stu)p2)->age;
如果前者大于后者就返回大于0的数,如果是升序的话,那么就要将这个较大的数和这个较小的数进行交换,因为我们要实现升序的效果,就是从小到大
如果想实现降序的话,我们将逻辑反过来:
return ((struct Stu)p2)->age-((struct Stu)p1)->age;
后面的大于前面的,返回值是小于0的数,因为要实现降序,那么我们就将较大的数与较小的数进行交换
咱们仔细想想,
对于qsort函数来讲,我们交换数组元素的条件是啥呢?
就是这个返回的值
如果我们写的是前面的值减去后面的值大于0的话就进行交换,就是前面的数大于后面的数,把大的换后面去,所以这种写法代表的排序顺序就是升序
假如后面的值大一些呢,就是前面值减去后面的值小于0,就是说后面的大,前面的小,就将这两个数进行交换,那么大的值都在前面,小的值在后面,那么我们就实现了降序了
就是对于qsort来说,我们这个快速排列需要交换满足条件的值,那么这个比较函数里面的条件就是这个满足交换条件的值交换的条件,就是return 后面的条件,如果这个返回值大于0的话就将这两个数进行对调了
p1-p2>0我们就对调这两个数----大的换后面去,---升序
p2-p1>0我们就对调这两个数----大的换前面去----降序
qsort函数的模拟实现
//我们是否能将bubble_sort函数改造成通用的算法,可以排序任意类型的数据
//模仿qsort
struct stu
{char name[20];int age;
};
int cmp_stu_by_name(const void* p1, const void* p2)
{return strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name);
}int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}
int cmp_stu_by_age(const void* p1, const void* p2)
{return ((struct stu*)p1)->age - ((struct stu*)p2)->age;
}void Swap(char* buf1, char* buf2, size_t width)//传过来的是hcar*指针,那么我们就用char*接受
{char tmp = 0;for (int i = 0; i < width; i++)//因为不知道两个元素之间有多少个字节,那么我们就把每个字节进行交换{tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;//这里仅仅只是交换一对字节,因为char类型是1个字节//交换完这一对字节,那我们就换下一对字节进行交换,因为buf1和buf2都是指针,那么我们利用指针的加减来实现字节间的加加buf1++;buf2++;//这个循环总共进行width次,每次一对字节交换}
}//size_t是无符号整型
void bubble_sort(void *base,size_t sz,size_t width,int(*cmp)(const void*p1, const void* p2))//将函数的形参改成void*,因为我们不知道传过来的是什么类型的数据
//而恰好void*可以接收任意类型的地址,那么bubble_sort这个函数就能处理任意类型的数据了//这里的base指向的是数组的首元素的地址,sz是数组元素个数
//仅仅知道这两个消息是仅仅不够的,因为我们不知道每个元素的字节大小是多少,因为不同类型的元素字节大小不同//解释一下这个函数,第一个接收的是数组首元素的地址,第二个是数组元素个数,第三个是元素之间的宽度,就是字节大小
//第四个就是比较函数
{//趟数for (int i = 0; i < sz-1; i++){//一趟内部的两两比较for (int j = 0; j < sz - 1 - i; j++){//唯一要改变的就是下面的比较的代码了//1.比较两个元素if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)//如果比较函数的返回值大于0,就进行交换//如果传过去的元素满足条件大于0满足交换的条件,那么就进入条件语句进行交换//那么我们需要将arr[j]的地址和arr[j+1]的地址传到比较函数进行大小比较//元素之间的字符大小根据j的变化来表示,j*width//将base强制转换成char*指针,因为对于char*来说,加几就是跳过几个字节//(char)base+width{//2.交换两个元素Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);//将起始地址传过去,但是并不知道交换多宽的数据,我们就一定得将宽度传过去//将两个交换的元素传过去,还有宽度也传过去
//交换的是(char*)base + j * width和 (char*)base + (j + 1) * width这两个地址指向的元素}}}
}
print(int arr[], int sz)
{for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}
}void test1()
{int arr[] = { 3,1,7,9,4,2,6,8,0 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);//cmp_int就是最前面的比较函数print(arr, sz);
}void test2()
{struct stu arr[] = { {"zhangsan", 20},{"lisi",35},{"wangwu", 18} };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);}
void test3()
{struct stu arr[] = { {"zhangsan", 20},{"lisi",35},{"wangwu", 18} };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}int main()
{test1();//对于整型数组//test2();//对于结构体--姓名//test3();//对于结构体--年龄return 0;
}//p1和p2指向的是我要比较的两个元素
//因为排序我们得知道他们的大小才能进行,那么这个bubble_sort的第四个形参的那个比较函数的返回值就体现了他们的大小
//
//
//
//
// 对于不同的类型的数据间的比较,我们要将内循环里面的比较条件语句进行改变
//
//
// 整理一下:
// 拿这个整数数组排列来说
//
// 首先我们先创建了一个test函数,test函数里面有数组的创建和数组长度的计算,还有一个冒泡函数
//
// 对于冒泡函数,
// 我们传过去了一个首元素的地址--就是数组名
// 还传过去数组的长度
// 还有数组元素之间的宽度,因为我们不知道不同元素间的宽度
// 最后还传了一个比较数组函数的函数名字
//
//
//
// 在经典的冒泡函数中,我们利用两层循环对数组进行排序
//
// 而面对不同的元素的时候,这个比较的条件一定是要进行更换的,但是两层循环可以不用动
//
//
// 在我们创建冒泡函数接受传来的实参的时候,有这么几个元素
//
// 我们用void*base来接受传来的数组名,因为我们并不知道传来的是什么类型的数据,恰好void*类型就可以接待任何类型的数据了
//
// 在后面,我们创建了size_t sz来接受数组长度,size_t就是无符号整型的意思
//
// 在后面我们又创建了一个size_t width,用来接收传来的数组中元素之间的字节宽度
//
// 最后,因为下面传来的实参是比较数组中两个相邻元素的函数,那么我们就用一个函数指针进行接收,一定是比较函数哦
// 在这个函数指针创建的时候,可是有说法哦
// int(*cmp)(const void *p1,const void *p2)
//返回类型是整数的函数指针,返回类型有三种,大于0,等于0,小于0的整数
// 利用返回的值进行判断,判断是否交换这两个相邻的元素的位置
//
// 而里面的const void *p1就是来接受任何类型的地址
//
// 说完冒泡排序的外面,再说里面吧
//
// 出了基本的两层循环,改变的就是里面的条件语句
// if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
// 利用传来的比较函数,我们比较了数组中相邻的两个元素的大小,如果返回值>0,我们就让这两个相邻的元素进行交换
// 将base的指针类型强制转换成char*类型的指针
// (char*)base + j * width这个就是这个比较函数的第一个元素,也是起始点
// (char*)base + (j + 1) * width这个是第二个元素,结束点
//
// 将两个元素传到比较函数里面,返回的值就是return *(int*)p1-*(int*)p2
//
// 可能你们又忘了为什么这么写:
// p1的类型在上面是void*类型,我们就需要将其强制转换到整型元素,再对其进行解引用操作,返回的值就是这两个元素之间的差值,反应两个元素的大小
//
//
// 为什么后面还有j*width呢?
// 随着j的变化,从0到sz-1-i,因为char类型的数据是1个字节的,如果我们有了width了,我们就知道我们该从哪里比较,到哪里停止了
//
//
//
// 那么就进入这个if条件语句里面的Swap交换函数了
//
// 这个交换函数可有意思
// 传过来的元素地址:(char*)base + j * width, (char*)base + (j + 1) * width,width
//
// 因为传过来的是地址,所以我们就用指针进行接收,我们还接受了元素的宽度
// 在这个函数里面,我们创建了一个临时变量tmp
// 还创建了一个循环 ,i从0开始,到width结束,就是循环width次,有多少个字节就交换几次,下面的就是很常见的交换的步骤了
// 但是是指针之间的交换,这些指针都是1个字节,因为传过来的是char*类型的指针
//
// 再后面,就进行指针++,换另一个字节,直到两个元素之间的字节都交换完成,那么这两个元素就交换完成了
// 交换四对字节
//
//这些代码没有具体类型的要求,你只要传一个数据,我们都能接受
// 因为我们使用void*类型的指针进行存储的
相关文章:
C语言---深入指针(4)
回调函数 //回调函数就是通过函数指针调用的函数 //这个在之前的转移表-计算器里面很明显,通过函数指针数组内的函数指针进行函数的调用 // // // 将这四段代码分装成一个函数,一个代码将这4个问题都解决 int Add(int x, int y) {return x y; } int S…...
【启程Golang之旅】让文件操作变得简单
欢迎来到Golang的世界!在当今快节奏的软件开发领域,选择一种高效、简洁的编程语言至关重要。而在这方面,Golang(又称Go)无疑是一个备受瞩目的选择。在本文中,带领您探索Golang的世界,一步步地了…...
oracle视图无法删除,orcl视图删除卡住怎么办
话说,这是一个来自周四加班夜晚的故事,当时我的PL/SQL卡住了,每次查询这个表时都会卡住。 经过一番研究,我找到了解决办法,分为三个步骤: 使用以下查询语句获取正在执行的SQL查询的SID和OracleID…...
ug编程怎么录制宏:一步步探索自动化编程的奥秘
ug编程怎么录制宏:一步步探索自动化编程的奥秘 在UG编程的浩瀚领域中,录制宏是一项强大而神秘的功能。它就像一位魔法师,能够将繁琐的重复操作化为简单的指令,释放出惊人的编程效率。然而,对于许多初学者来说…...
深度学习Week16——数据增强
文章目录 深度学习Week16——数据增强 一、前言 二、我的环境 三、前期工作 1、配置环境 2、导入数据 2.1 加载数据 2.2 配置数据集 2.3 数据可视化 四、数据增强 五、增强方式 1、将其嵌入model中 2、在Dataset数据集中进行数据增强 六、训练模型 七、自定义增强函数 一、前言…...
python-自幂数判断
[题目描述]: 自幂数是指,一个N 位数,满足各位数字N 次方之和是本身。例如,153153 是 33 位数,其每位数的 33 次方之和,135333153135333153,因此 153153 是自幂数;16341634 是 44 位数…...
RocketMQ教程(三):RocketMQ的核心组件
四个核心组件 RocketMQ 的架构采用了典型的分布式系统设计理念,以确保高性能、高可用和可扩展性。RocketMQ 主要由四个核心组件构成:NameServer、Broker、Producer 和 Consumer。下面是对这些组件以及它们在 RocketMQ 中的角色和功能的概述: 1. NameServer 角色和功能:Name…...
46.SQLserver中按照多条件分组:查询每个地方的各种水果的种植数量,新增时,一个地方同时有几种水果,只插入一条记录,同时多种水果之间使用|隔开
1.SQLserver中按照多条件分组 ,分组条件包括(一个字段使用|进行分割,如:apple|orange,查询时,apple和orange分别对应一条数据) 例如:SQL如下: SELECT FROM ( SELECT CDFBM 地方编码…...
C盘满了怎么办,Windows11的C盘没有磁盘清理选项怎么办,一次搞定
问题: 太久没清电脑了,满的跟垃圾堆一样。。。C盘红色看上去很不妙。 一. C盘满了怎么办: 1. 删除临时文件 找到 C:\Windows\Temp,进入Temp资料夹,选中所有文件夹和文件,按下ShiftDelete键,彻…...
「动态规划」当小偷改行去当按摩师,会发生什么?
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),…...
Python | 排队取奶茶
队列的基本概念(队头、队尾)和特点(先入先出) 在 Python 语言中,标准库中的queue模块提供了多种队列的实现,比如普通队列和优先级队列,因此你可以使用queue.Queue类来创建队列,不过…...
mysql当前状态分析(show status)
文章目录 查看当前线程数据查询连接情况查询缓存相关查询锁相关查询增删改查执行次数查询DDL创建相关 SHOW STATUS 是一个在 MySQL 中用来查看服务器运行状态的命令。它可以帮助你了解服务器的当前性能,包括连接数、表锁定、缓冲区使用情况等信息。 查看当前线程数据…...
Google Earth Engine(GEE)——使用机器学习进行金三角大米分布图
第 1 步:转到https://code.earthengine.google.com/打开代码编辑器 第 2 步:使用以下代码从 Google Earth Engine Asset 导入数据 // 导入影像集合 var composites = ee.ImageCollection("projects/servir-mekong/yearlyComposites"); // 导入训练数据 var data …...
MyBatis一级和二级缓存介绍
MyBatis是一个持久层框架,它提供了一级缓存和二级缓存来提高数据库操作的性能。下面是一级缓存和二级缓存的区别理解、画图和知识点总结: 一级缓存: 一级缓存是MyBatis默认开启的缓存层,它是SqlSession级别的缓存,也…...
PowerDesigner遍历导出所有表结构到Excel
PowerDesigner遍历导出所有表到Excel 1.打开需要导出表结构到Excel的pdm文件 2.点击Tools|Execute Commands|Edit/Run Script菜单或按下快捷键Ctrl Shift X打开脚本窗口,输入示例VBScript脚本,修改其中的Excel模板路径及工作薄页签,点Run…...
JavaSE——抽象类和接口
目录 一 .抽象类 1.抽象类概念 2.抽象类语法 3.抽象类特性 4.抽象类的作用 二. 接口 1.接口的概念 2.语法规则 3.接口的使用 4.接口特性 5.实现多个接口 6.接口间的继承 三.抽象类和接口的区别 一 .抽象类 1.抽象类概念 在面向对象的概念中,所有的对…...
生成式人工智能 - stable diffusion web-ui安装教程
一、Stable Diffusion WEB UI 屌丝劲发作了,所以本地调试了Stable Diffusion之后,就去看了一下Stable Diffusion WEB UI,网络上各种打包套件什么的好像很火。国内的也就这个层次了,老外搞创新,国内跟着屁股后面搞搞应用层,就叫大神了。 不扯闲篇了,我们这里从git源码直接…...
11-Linux文件系统与日志分析
11.1深入理解Linux文件系统 在处理Liunx系统出现故障时,故障的症状是最易发现。数学LInux系统中常见的日志文件,可以帮助管理员快速定位故障点,并及时解决各种系统问题。 11.1.1 inode与block详解 文件系统通常会将这两部分内容分别存放在…...
mac M1下安装PySide2
在M1下装不了PySide2, 是因为PySide2没有arm架构的包 1 先在M1上装qt5 安装qt主要是为了能用里面的Desinger, uic, rcc brew install qt5 我装完的路径在/opt/homebrew/opt/qt5 其中Designer就是用来设计界面的 rcc用resource compiler, 编绎rc资源文件的, 生成对应的py文件…...
超详解——识别None——小白篇
目录 1. 内建类型的布尔值 2. 对象身份的比较 3. 对象类型比较 4. 类型工厂函数 5. Python不支持的类型 总结: 1. 内建类型的布尔值 在Python中,布尔值的计算遵循如下规则: None、False、空序列(如空列表 [],空…...
C++的MQTT开发:使用Paho的C++接口实现消息发布、订阅、连接RabbitMQ
C Paho实现MQTT消息发布功能 要使用paho的cpp接口实现发布MQTT消息的功能,需要进行以下步骤: 安装paho库:首先从paho官方网站下载并安装paho的C库。可以从https://www.eclipse.org/paho/clients/cpp/ 下载适合操作系统的版本。 创建MQTT客户…...
深度网络学习笔记(二)——Transformer架构详解(包括多头自注意力机制)
Transformer架构详解 前言Transformer的整体架构多头注意力机制(Multi-Head Attention)具体步骤1. 步骤12. 步骤23. 步骤34. 步骤4 Self-Attention应用与比较Self-Attention用于图像处理Self-Attention vs. CNNSelf-Attention vs. RNN Transformer架构详…...
Python 快速查找并替换Excel中的数据
Excel中的查找替换是一个非常实用的功能,能够帮助用户快速完成大量数据的整理和处理工作,避免手动逐一修改数据的麻烦,提高工作效率。要使用Python实现这一功能, 我们可以借助Spire.XLS for Python 库,具体操作如下&am…...
KafkaStream Local Store和Global Store区别和用法
前言 使用kafkaStream进行流式计算时,如果需要对数据进行状态处理,那么常用的会遇到kafkaStream的store,而store也有Local Store以及Global Store,当然也可以使用其他方案的来进行状态保存,文本主要理清楚kafkaStream…...
PowerDesigner导入Excel模板生成数据表
PowerDesigner导入Excel模板生成数据表 1.准备好需要导入的Excel表结构数据,模板内容如下图所示 2.打开PowerDesigner,新建一个physical data model文件,填入文件名称,选择数据库类型 3.点击Tools|Execute Commands|Edit/Run Script菜单或按下快捷键Ctrl Shift X打开脚本窗口…...
STM32 HAL库开发——入门篇(3):OLED、LCD
源自正点原子视频教程: 【正点原子】手把手教你学STM32 HAL库开发全集【真人出镜】STM32入门教学视频教程 单片机 嵌入式_哔哩哔哩_bilibili 一、OLED 二、内存保护(MPU)实验 2.1 内存保护单元 三、LCD 3.1 显示屏分类 3.2 LCD简介 3.3 LCD…...
在Linux中查找文件命令的几种方法
要在Linux中查找文件,可以使用以下几种不同的实现方法: 1. 使用find命令: find <搜索路径> <搜索选项> <搜索条件><搜索路径>:表示要搜索的起始路径,可以是一个具体的目录路径,也…...
【TB作品】MSP430F5529 单片机,温度控制系统,DS18B20,使用MSP430实现的智能温度控制系统
作品功能 这个智能温度控制系统基于MSP430单片机设计,能够实时监测环境温度并根据预设的温度报警值自动调节风扇和加热片的工作状态。主要功能包括: 实时显示当前温度。通过OLED屏幕显示温度报警值。通过按键设置温度报警值。实际温度超过报警值时&…...
立创小tips
立创小tips 原理图中 1-修改图纸属性 保存完,绘制原理图的界面就出现了,然后我们鼠标点击原理图的边缘变成红色就可以高边表格的属性了。 2-鼠标右键可以移动整个原理图 3-查看封装 点击任意一个元器件,在右侧就会显示封装属性ÿ…...
Html/HTML5常用标签的学习
课程目标 项目实战,肯定就需要静态网页。朝着做项目方式去学习静态网页。 01、编写第一个html工程结构化 cssjsimages/imgindex.html 归档存储和结构清晰就可以。 02、HTML标签分类 认知:标签为什么要分类,原因因为:分门别类…...
西安公司做网站/windows优化大师最新版本
cmd 进入E文件夹 E: 查看文件夹目录 dir 进入某个文件夹 cd 目录...
建网站公司是如何赚钱/成人短期电脑培训班学费
在C中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符: 1、插入器(<<) 向流输出数据。比如说系统有一个默认的标准输出流(cout),一…...
优秀购物网站/技能培训网站
算法提高 淘淘的名单 时间限制:100ms 内存限制:8.0MB 问题描述 by ZBY… ? 淘淘拿到了一份名单,他想对上面的名字进行处理,挑出一些特殊的名字,他请你来帮忙。 淘淘关注以下名字: 如果这个名字…...
网站提交 入口/灰色项目推广渠道
1、首先确保已经建立了模拟器2、首先修改activity_main.xml,把内容写在android:text""中,我要修改的是图书管理系统,可以通过更改android:textSize"20px" 的数值,更改“图书管理系统”字体的大小。3、下面要生…...
批量替换wordpress文章中的文字/国内seo服务商
*** __asm void MSR_MSP(u32 addr) //__asm 关键字用于调用内联汇编程序,用来声明一个C语言函数的话, // 代表这个函数内都是汇编语句 { MSR MSP, r0 …...
网站缺点/网络推广渠道有哪些
本文不讲架构,不扯淡,上来就是命令和代码直接开干!就是入门和学习,完整的基础构成组件全部堆在一台机器上。有问题请留言。 一台机器安装四个组件 chef server chef manage chef workstation chef client系统环境为ubuntu16.04&a…...