C语言之指针详解(7)

目录
本章重点
1. 字符指针
2. 数组指针
3. 指针数组
4. 数组传参和指针传参
5. 函数指针
6. 函数指针数组
7. 指向函数指针数组的指针
8. 回调函数
9. 指针和数组面试题的解析
上一篇博客我们说过会把回调函数的一些知识再给大家讲一遍
这里把void*强制类型转化为struct Stu*,用->操作符找到age这个元素,然后对年龄进行快速排序

//void qsort(void* base, size_t num, size_t size,int (*compar)(const void*e1, const void*e2));
#include<stdio.h>
#include<stdlib.h>
struct Stu
{
	char name[20];
	int age;

};
int cmp_stu_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
void test()
{
	struct Stu s[3] = { { "zhangsan", 20 }, { "lisi", 30 }, { "wangwu", 10 } };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}
int main()
{
	test();
	return 0;
}
那我们如果要将字符串进行快速排序,我们还是按照age的排序方式来排序嘛?答案是不是,这里我们要用到字符串比较函数strcmp,现在我们来看下列代码,F11走到函数内部进行排序,我们看到的结果就是lisi  wangwu zhangsan
//void qsort(void* base, size_t num, size_t size,int (*compar)(const void*e1, const void*e2));
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Stu
{
	char name[20];
	int age;

};
int cmp_stu_by_name(const void* e1, const void* e2)
{
	//比较名字就是比较字符串
	//字符串比较不能直接<>=来比较,需要用到strcmp函数
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
	//return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
void test()
{
	struct Stu s[3] = { { "zhangsan", 20 }, { "lisi", 30 }, { "wangwu", 10 } };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}
int main()
{
	test();
	return 0;
}
这里再次给大家把qsort函数强调一下
void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));

第一个参数:待排序数组的首元素的地址

第二个参数:待排序数组的元素个数

第三个参数:待排序数组的每个元素的大小,单位为字节

第四个参数:是函数指针,比较两个元素的所用函数的地址,这个函数使用者自己实现,函数指针的两个参数是待比较的两个元素的地址

#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}
void _swap(void* p1, void* p2, int size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *((char*)p1 + i);
		*((char*)p1 + i) = *((char*)p2 + i);
		*((char*)p2 + i) = tmp;
	}
}
void bubble(void* base, int count, int size, int(*cmp)(void*, void*))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < count - 1; i++)
	{
		for (j = 0; j < count - i - 1; j++)
		{
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
				_swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}
int main()
{
	int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
	//char *arr[] = {"aaaa","dddd","cccc","bbbb"};
	int i = 0;
	bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

这里给大家详细解释一下这个代码

为什么我们要写cmp((char*)base + j * size, (char*)base + (j + 1) * size)呢???

因为当j=0的时候,这个函数的参数就代表第一个元素和第二个元素的地址,强制类型转化为char*而不是Int*的原因是强制类型转化为Int*然后+1会让地址向后移动四个字节,对于如果我们给你传过来的是一个结构体类型,double型,float型就不合适,所以Int*不考虑,对于为什么要强制类型转换为char*指针,char*指针加1跳过一个字节,当我+size的时候就跳过size个字节,这是我们就把我们相邻两个元素的地址求出来了,然后把地址带到cmp这个函数中去了,但他返回cmp函数的值大于0,我们就进行交换,那我们应该怎么交换呢???这里我们就设计一个_swap函数,传的参数是(char*)base + j * size, (char*)base + (j + 1) * size, size,我们为什么还要传一个size呢?因为你应该告诉我你这个两个字符各是几个字节,让我交换相应的对数,所以我们应该把这个元素的大小传过去,我们进到_swap函数进行交换,交换完了过后再*p1++,*p2++指向下一个值 ,再进行下一组交换,接着我们再写出这行代码,看下面代码,进行正负数的返回,返回给cmp函数判断正负数,是整数就进行交换,希望大家能够理解

#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}

这是一个一般的冒泡排序的模型,上面的代码就只是这个一般的冒泡排序的一个升华,本质是没变的,里面的排序还是正常的将两个元素进行交换,直到交换成升序为止

扫描二维码关注公众号,回复: 15340850 查看本文章

这里再给大家做一下说明

使用bubble_sort的程序员一定要知道自己排序的是什么数据,他就应该知道如何比较待排序数组中的元素,实现bubble_sort函数的程序员,他不知道未来排序的数据类型,那程序员也不知道待比较的两个元素的类型

本章终!

猜你喜欢

转载自blog.csdn.net/fjj2397194209/article/details/131247008