一 数组指针的简绍与理解:
1·可想而知便或有个相似的名字出现在我们脑海中,那便就是指针数组,它和整型数组或者字符型数组一样是个数组;如:
int arr[]={1,2,3};//整型数组
char str[]={'a','b'};//字符型数组
int *p[]={&a,&b,&c};//指针数组
接下来我们来介绍一下所谓的数组指针的概念:明显,它是一个存放数组的指针变量,也就是说它是一个指针,指向的是某个数组的首地址来方便我们找到此数组的那些元素;下面是他的写法:
int p[10]=&arr;
int(p)[10]=&arr;//数组指针:指针是p,它所指向的是数组名为arr,元素为10个,类型为int的数组的首地址
这样我们就可以理解在传送地址时的arr+1与&arr+1的区别了,前者是一个地址加一,跳过的是一个地址所占字节数,而后者可以借助数组指针来理解,它是&arr指向的是一个数组,而加一便变成了下一个数组,所以它跳过的应是一个数组所占的字节数。而这个数组指针类型就为:int()[10];
2·那用这个数组指针我们可以干什么呢?下面我们来用它打印一下二维数组吧;
void print(int(p)[2],int m,int n) {//这个地址直接传给函数的话,这个指针p直接指向此数组首地址
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
printf("%d ", ((p + i))[j]);//这里也可也可以是((p+i)+j);这里()应该要注意一下:不能写成(p+i)[10],因为的优先级比()[]低;
}
printf("\n");
}
}
int main() {
int arr[3][2] = { {1,2},{2,3},{5,6} };
print(arr,3,2);//我们通过一个函数来打印它
return 0;
}
这样的话便实现了用数组指针对二维数组进行打印。
二 函数指针 :
1·顾名思义,函数指针,它也是一个指针,指向的便是一个函数:首先我们先定义这个指针便可以对它进行调用:下面我们可以写一个简单的代码应用一下吧!
int add(int a, int b) {
return a + b;
}
int main() {
int m = 0;
int n = 0;
printf("请输入你要计算的两个数;\n");
int (p)(int, int) = &add;//这里也可以直接写成add,我们可以看出它和数组指针区别[]改为了()内里面存放的是函数形参类型
scanf("%d %d", &m, &n);
int ret = (p)(m, n);//这里调用一下这个函数把它的返回值用ret接收
printf("两数相加为:%d\n",ret);
return 0;
}
三 函数指针数组理解及应用:
1.定义:首先它是把多个同类型函数指针放在同一个数组中的;可以简单理解为由函数指针改造而来;
int (*pfarr[4])={函数名,函数名,函数名,函数名};
他是个数组,类似int arr[4]={0};只不过把名字arr提到括号里面了。
然后我们便可以定义函数来使用它:
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(parr[5]) (int,int) = {NULL,add,sub,mul,div};
do {
printf("请选择对应数字:\n");
scanf("%d", &input);
if (input >= 1 && input <= 4) {
printf("请输入要计算的两个数:\n");
scanf("%d %d", &x, &y);
int ret = (*parr[input])(x, y);
printf("%d", ret);
}
if (input == 0) {
printf("退出\n");
}
} while (input);
return 0;
}
以上;就是我们用函数指针数组来实现的一个简单的加减乘除计算器;
2.回调函数:顾名思义,就是函数调用了函数地址然后进行使用,此回调函数用指针来接收,如:
include
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 xy;
}
int Div(int x,int y)
{
return x/y;
}
void cal(int (pf)(int ,int ),int x,int y)//这里用一个函数指针来接收
{
int ret = *pf(x,y);
printf("%d\n",ret);
}
int main()
{
cal(Add,2,4);//cal就为一个回调函数里面为调用的函数的地址与其他数据
cal(Sub,2,4);
cal(Mul,2,4);
cal(Div,2,4);
return 0;
}
以上就是对回调函数的简单理解。
四 qsort的定义以及应用 :
1.我们简单介绍一下qsort是一个库函数,它可以用来排序整型数组,字符型数组以及结构体;与我们以前学的冒泡排序的区别有它可以排列乱序的数字,而它采用的是最底层的快速排序。
其头文件为#include
写法:
void qsort(voidbase,size_t num,size_t size,int (compar)(const void,const void))
//base为指针指向的是待排序数组的首元素,num为base所指向的数组元素个数,size为一个元素的种类所占字节数而最后者返回的是一个两个元素的比较函数。返回的是int类型
qsort(arr,sz,sizeof(arr[0]),cmp_int)//调用这个库函数列。
下面我们分别用这个qsort函数来给整形数组,字符型数组,结构体型数组进行一下排序:下面由代码等来展示:
//qsort函数整型排序//
int com(const void p1, const void p2) {
return (int)p1 - (int)p2;将指针p1强制类型转化为int*,(一开始指针为任意类型无法应用),在做比较时俩个指针所指向内容相减,分别返回正数交换,负数不交换,零也是。
}
void print(int* p,int sz) {
for (int i = 0; i < sz; i++) {
printf("%d", *(p+i));
}
}
int main() {
int arr1[5] = { 55,44,77,33,99 };
int sz = sizeof(arr1) / sizeof(arr1[0]);
qsort(arr1,sz,sizeof(int),com);
print(arr1, sz);
return 0;
}
qsort函数字符型排序
int com(const void* p1, const void* p2) {
return *(char*)p1 - *(char*)p2;//因为这里排序的是字符数组,故指针也应该是char*,比较的是ascii码值
}
void print(char arr2[], int sz) {
for (int i = 0; i < sz; i++) {
printf("%c ", arr2[i]);
}
}
int main() {
char arr2[5] = { 'c','r','a','m' ,'\0'};
int len = strlen(arr2);
qsort(arr2, len, sizeof(char), com);
print(arr2, len);
return 0;
}
/qsort函数对结构体排序//
struct stu {
int age;
char name[20];
};
int com(const void* p1, const void* p2) {
return strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name);
}//这里用了strcmp来比较两个字符串:而比较时是比较ascii遇到大的立即停止比较如:abf>abcde
void prints(struct stu *p) {
for (int j = 0; j < 3; j++) {
printf("%d %s ", (p + j)->age,(p + j)->name);
}
}
int main() {
struct stu s[3] = { {1,"zhangsan"},{4,"lisi"},{2,"wangwu"} };
qsort(s, 3, sizeof(s[0]), com);
prints(s);
return 0;
}
2.自行实现的qsort函数应用:
我们可以通过最简单的冒泡排序对其进行改造成可以对于任意类型数组排序的函数,下面可通过这个冒泡排序进行改造:
define _CRT_SECURE_NO_WARNINGS
include
void bubble_sort(int* arr, int sz)
{
int i = 0;
for (i = 0; i < sz-1; i++)
{
int j = 0;
for (j = 0; j arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
下面我们展示改后的的qsprt函数的实现:
自创my-qsort:/
int com(const void p1, const void p2) {
return (int )p1 - (int)p2;
}
void swap(char m1, char m2,int width) {
for (int i = 0; i < width; i++) {
char temp = m1; m1 = m2; m2 = temp;
m1++;
m2++;
}//我们交换两个地址,因为不知道他的类型,即指针访问的到下一个地址要移动的距离,可以将每一个地址分为类型所对应的字节数,用char*最小访问一个单位来进行访问故假设是整型那么一个地址四个字节也就是m1应该移动width次,可完全交换玩一对地址
}
void my_sort(void base, size_t sz,size_t width,int(com)(const void p1,const void p2)){
for (int i = 0; i < sz - 1; i++) {
for (int j = 0; j < sz - i - 1; j++) {
if (com((char)base+jwidth, (char)base + (j+1) width)>0) {
swap((char)base + j width, (char)base + (j + 1) width,width);
}//这里由于我们不知道要排序的数组是什么类型,以及一个元素字节数,因此我们先给它把字节数定为宽度而把指针强制转化成char方便通过char指针每次访问一个字节来找到它的地址所在。我们假设是一个整型的话那么就是四个字节,我们要传两个相邻地址,故第二个地址就相当于第一个地址往后访问四个字节故第一个指针移动到第二个指针因该是+jwidth,后一个就是j+1;
}
}
}
print(int p, int sz) {
for (int i = 0; i < sz; i++) {
printf("%d ", *(p + i));
}
}
int main() {
int arr[5] = { 44,34,57,89,1 };
int sz = sizeof(arr) / sizeof(arr[0]);//这里我们把它来计算整型数组,
my_sort(arr, sz, sizeof(arr[0]),com);
print(arr,sz);
return 0;
当然我们可以用它来排序不同类型的数组,到时直接改一下所传送的数据即可。
以上就是简单的一些自己的理解,在知识的海洋中,我自觉如微尘般渺小,深感自身学识之不足。恳请这方面大佬们不吝赐教,以您的智慧之光,照亮我前行的道路。愿在您的指导下,我能够不断进步,弥补自身的不足,更好地领悟人生的真谛。