1.回调函数:
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
冒泡排序:(局限性:该冒泡排序数组只能排整型数)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<limits.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
int 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 = arr[j];
arr[j ] = arr[j+1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
插入:void* pa的意思是没有类型的指针;int* pa是整型指针;char* pa是字符型指针;
void* pa的好处在于不会出现类型不匹配的警告。可以接收任何类型的地址----int char等等。
void*类型的指针不能进行解引用操作(void没有具体的类型,解引用操作时不知道访问几个指针)
void*类型的指针不能进行加减的操作;
2.库函数qsort-------C语言中提供的库函数-------可以排序任意类型的数据;----quick sort快速排序
库函数qsort的头文件为 #include<stdlib.h>
qsort函数的第一个参数:待排序数组的首元素地址;第二个参数:待排序数组的元素个数;第三个参数:待排序数组每个元素的大小--单位是字节;第四个参数:函数指针,比较两个元素所用函数的地址--这个函数使用者自己体现。函数指针的两个参数:待比较的两个元素的地址。
使用库函数qsort快速进行排序(冒泡排序)
对浮点型进行排序:
结构体同样也可以打印:(比较年龄)但是比较名字不能直接用大于小于;
因为名字是字符,所以名字按照顺序不可以直接用大于或者小于来比较:在此引用函数 strcmp进行字符的比较: strcmp 函数使用时需要引用头文件 #include<string.h>
3.调用函数指针;熟悉数组指针、指针数组、函数指针的区别;
尤其注意:函数指针的初始化,int(*pAdd)(int,int)=Add; int 是指针类型--整型;*pAdd是指针;尤其注意后面(int,int)表示参数的类型;需要根据你定义的函数去确定;定义Add为int x,int y为整型,所以括号里面填(int,int)。
函数指针的数组:int(*parr[5])(int,int)=&parr;
指向函数指针数组的指针:int(*(*pparr)[5])(int,int)=&parr;
4.仿照qsort的功能定义bubble_sort函数实现冒泡排序:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<limits.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
int cmp_int(const void*e1, const void*e2)
{
return *(int*)e1 - *(int*)e2;
}
void swap(char*buf1, char*buf2,int width)
{
int i = 0;
for (i = 0; i < width; i++)
{
char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
*buf1++;
*buf2++;
}
}
void bubble_sort(void* base, int sz, int width, int(*cmp)(void* e1, void* e2))//仿照qsort函数的方式
{//void*base表示首元素的地址;int width表示被传数组元素的大小;int(*cmp)(void* e1, void* e2)表示指针
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{//两个元素作比较,进行交换
if (cmp((char*)base + j*width, (char*)base + (j + 1)*width) > 0)
{//强制类型转换为char*可以进行加减法;+j*width表示一直向后循环
swap((char*)base + j*width, (char*)base + (j + 1)*width, width);
}//因为不知道需要交换几次,所以需要把width也传过去
}
}
}
void test()
{
int arr[] = { 7, 8, 9, 10,11, 2, 3, 4, 5, 6, 100 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
test();
return 0;
}
注意:之所以强制类型转换为char*,是因为char*可以进行运算。
bubble_sort函数是cmp_sort,所以上边必须用*cmp指针来接收;
5. 注意:数组名绝大多数是表示首元素的地址
但是有两种例外(切记)1. sizeof(数组名)----数组名表示整个数组;
2. &数组名 ----数组名表示整个数组;
凡是地址:他的字节大小不是4就是8(切记)
int main()
{
int a[] = { 1, 2, 3, 4 };// sizeof(a)计算数组总大小,单位是字节;
printf("%d\n", sizeof(a));// 16 4个元素,每个元素4个字节
printf("%d\n", sizeof(a + 0));//4
printf("%d\n", sizeof(*a));//4
printf("%d\n", sizeof(a + 1));//4
printf("%d\n", sizeof(a[1]));//4
printf("%d\n", sizeof(&a));//4
printf("%d\n", sizeof(*&a));//16
printf("%d\n", sizeof(&a + 1));//4
printf("%d\n", sizeof(&a[0]));//4
printf("%d\n", sizeof(&a[0] + 1));//4
}
第一个:sizeof(a) 取出的是整个数组的大小;4个元素每个元素4个字节;
第二个:sizeof(a+0) 数组名这里表示首元素的地址,a+0还是首元素的地址;只要是地址就是4/8;
第三个:sizeof(*a) 数组名表示取出首元素的地址;*a就是首元素,所以还是4;
第四个:sizeof(a+1) 数组名表示首元素的地址,a+1还是首元素的地址;所以还是4;
第五个:sizeof(a[1]) 数组名表示第二个元素的地址;
第六个:sizeof(&a) 数组名表示数组的地址,还是地址;
第七个:sizeof(*&a) &a表示整个数组的地址,解引用表示取出整个数组的地址,所以此时表示整个数组的大小;
第八个:sizeof(&a+1) &a是数组的地址,&a+1表示跳过整个数组;但还是地址;
第九个:sizeof(&a[0]) 数组名表示第一个元素的地址;
第十个:sizeof(&a[0]+1)数组名表示第二个元素的地址;
int main()
{
char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
printf("%d\n", sizeof(arr));//6
printf("%d\n", sizeof(arr + 0));//4
printf("%d\n", sizeof(*arr));//1
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//4
printf("%d\n", sizeof(&arr + 1));//4
printf("%d\n", sizeof(&arr[0] + 1));//4
}
第一个:数组名表示整个数组的大小,所以是6;
第二个:sizeof(arr+0)表示首元素的大小,a+0还是表示首元素的大小,所以是4/8;
第三个:sizeof(*arr) arr表示首元素的大小,*arr表示解引用首元素,所以表示第一个元素,所以是1;
第四个:sizeof(arr[1]) arr[1]表示第二个元素,所以是1;
第五个:sizeof(&arr) &arr表示整个数组的地址,所以不是4就是8;
第六个:sizeof(&arr+1) &arr表示整个数组的地址,&arr+1表示跳过整个数组,还是地址;
第七个:sizeof(&arr[0]+1) &arr[0]表示首元素的地址,&arr[0]+1表示第二个元素的地址,还是4/8;
int main()
{
char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };//strlen找结束符\0;
printf("%d\n", strlen(arr));//随机
printf("%d\n", strlen(arr + 0));//随机
//printf("%d\n", strlen(*arr));//
//printf("%d\n", strlen(arr[1]));//
printf("%d\n", strlen(&arr));//随机
printf("%d\n", strlen(&arr + 1));//随机-6
printf("%d\n", strlen(&arr[0] + 1));//随机-1
}
切记:strlen和sizeof的区别:sizeof是数组的大小,单位是字节;strlen是字符的长度,一定要找到\0结束标志才会结束;
第一个:arr表示整个数组,没有\0结束标志,所以是随机值;
第二个:arr+0表示首元素地址,+0还是随机值;
第三个:*arr,表示解引用首元素的地址,打印%d转成数值,error;
第四个:arr[1]表示第二个字符,打印%d还是数值,error;
第五个:&arr表示整个数组的地址,没有\0,还是随机值;
第六个:&arr+1表示在首元素的基础上,跳过一个数组,所以是随机值-6;6表示数组中原本存在的6个字符;
第七个:&arr[0]+1表示首元素+1,是第二个元素,所以从第二个元素开始,是首元素-1;