Simulate the implementation of qsort function (advanced C pointer)

Table of contents

One: pointer function

(1) What is a function pointer?

(2) The meaning of the function name.

Two: What is the qsort() function

(1) The function prototype of the qsort() function

(2): Parameter meaning of qsort() function

Three: bubble sort

(1): What is bubble sort?

(2) Diagram:

Four: callback function

(1): What is a callback function?

(2) Significance of the callback function

Five: Create source files and header files

Six: The specific implementation of the function

(1): function bubblesort( )

(2): comparison method (function)

(3) How to find the first address of the function element?

(4): How to exchange?

Seven: All codes

(1)cmp.h

(2)cmp.c

(3)bubble_sort.c

Eight: Conclusion


One: pointer function

(1) What is a function pointer?

Function pointer: First of all, it is a pointer, a pointer to a function, and the address of the function is stored in the memory space.

(2) The meaning of the function name.

We all know that the array name represents the address of the first element of the array in most cases. &The array name represents the address of the array. Although the values ​​are consistent, the meanings represented are completely different.

Then can we think that the function name is the first address of the space where the function is located, and the & function name (function pointer) represents the address of the function? Let's look at the example below.

a8e9d277133c4be780c10e0d928a024c.png

We can see that the values ​​of the two are the same, so do they have the same meaning as the array name and & array name? Let's look at references to function pointers below.

 6afdd5b3053f4670bd6849988f29701a.png

According to our original understanding of pointers, it seems that the function can only be found by dereferencing p plus *, but we can see that no matter how many * are added in front of the function name, the result is the same, so we come to the conclusion: the function name and & The function names are completely equivalent, no matter how many * are added in front of the function name, it has no effect. 

To make a summary: function name = & function name
array name! =& array name

Two: What is the qsort() function

(1) The function prototype of the qsort() function

void qsort(void *base, int nelem, int width, int (*fcmp)(const void *,const void *))

qsort (that is, quicksort) mainly provides a quick sort according to the comparison conditions you give, and mainly realizes the sorting function through pointer movement. The sorted results are still placed in the original array.

The qsort function is included in the header file stdlib.h.

(2): Parameter meaning of qsort() function

Before talking about the meaning of the parameters, let’s talk about the magic of the void type. When we learned about arrays in the early days, the function parameters passed in are generally pointers of the corresponding type of the array, so that only one data type can be received, and it will be more complicated if we want to modify it. , but the void type can receive any type , making the code more versatile.

But the void type is a meaningless type , we cannot directly use the void type to participate in the operation, nor can we dereference the pointer of the void type, unless a forced type conversion is performed .

The first parameter: void* is used to receive the address of the first element of the target array to be sorted .

The second parameter: num is the number of elements of the target array to be sorted .

The third parameter: width is the size of a single array element (that is, the number of bytes)

The fourth parameter: compare is a function pointer, that is, the user-defined comparison method (function)

Three: bubble sort

(1): What is bubble sort?

Bubble sort is a relatively simple sorting algorithm. It repeatedly visits the array to be sorted, compares two elements at a time , and exchanges them if they are in the wrong order. The work of visiting the sequence is repeated until no more swaps are needed .

(2) Diagram:

56c78d2e0a034225b9c009626fdaa6e2.png

Four: callback function

(1): What is a callback function?

A callback function is a function that is called through a function pointer. If you pass a function pointer (address) as a parameter to another function, when this pointer is used to call the function it points to, we say this is a callback function. The callback function is not directly called by the implementer of the function, but is called by another party when a specific event or condition occurs, and is used to respond to the event or condition.

Simply put, a callback function is to call a function inside another function through a function pointer under certain conditions.

(2) Significance of the callback function

We can look at the following example:

If we have four functions for addition, subtraction, multiplication, and division of integers, we need these functions in another function. If we don’t use function pointers, we need to write multiple judgment statements to make selections, which is not concise and not Conducive to subsequent code maintenance. If we pass in the function pointer as a parameter, the function function can call the corresponding function by modifying the parameter, without any modification itself.

fa80f7de485f44c998ec55e3aa581bb9.png

Five: Create source files and header files

Header file: cmp.h is used to include some necessary header files, declare functions or define structures.

Source file: cmp.c is used to define some comparison methods (functions)

bubble_sort.c is used to define the main function bubbleSort() for related tests.

Six: The specific implementation of the function

(1): function bubblesort( )

void bubbleSort(void* s, int sz,int size,int(*cmp)(const void*e1,const void*e2))

The parameter meaning of bubblesort( ) function is the same as that of qsort() function

Function definition:4ff32f31503348ad98192d2027d3cdcb.png

(2): comparison method (function)

The comparison function is defined by the user , which means that the user knows the data type to be compared . We need to receive the first address of the two elements of the array. At this time, the type of the address is an empty type, and we cannot directly dereference it. Casting , if the first element is greater than the second element, we return a number greater than 0, otherwise we return a number less than 0.

Comparison method of int type:

6379902210b34f349f23d11ce4e9351d.png

Comparison method of char type:

644fdb80c80448828cff14c7e7134296.png

The comparison method of the structure type (including the comparison method of the string type, note that the header file string.h is included ):

f69d4bb9879640aead5979fdf4de6a70.png85e5afe6c93c4e8a87fa56a26e42f462.png

(3) How to find the first address of the function element?

The size of a single element type of the array has been passed inside the function, and we can cast the passed address into (char*) , so that we can pass ((char*)s + size*j) and ((char*) s + size*(j+1)) Find the first address of the jth and j+1th elements, and then compare them.


Illustration:73ca08d1819c4e45a0b31796bdeb135c.png

(4): How to exchange?

We have mentioned char* coercion before, we can exchange each byte of the element , and the condition of the loop is determined by sz.

Illustration:

 

Function definition:74df56c0e42144979bfd4fd80585a496.png  

Seven: All codes

(1)cmp.h

#include <stdio.h>
#include <string.h>
//字符比较
int cmp_char(const void* e1, const void* e2);
//整形比较
int cmp_int(const void* e1, const void* e2);
//结构体定义
struct stu {
	char name[10];
	int age;
};
//结构体内部成员比较
int cmp_stu_name(const void* e1, const void* e2);
//结构体内部成员比较(字符串比较)
int cmp_stu_age(const void* e1, const void* e2);

(2)cmp.c

#include "cmp.h"

int cmp_char(const void* e1, const void* e2)
{
	return (*(char*)e1 - *(char*)e2);
}

int cmp_int(const void* e1, const void* e2)
{
	return *((int*)e1) - *((int*)e2);
}

int cmp_stu_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}

int cmp_stu_age(const void* e1, const void* e2)
{
	return (((struct stu*)e1)->age - ((struct stu*)e2)->age);
}


(3)bubble_sort.c

#include "cmp.h"
void swap(void* s1, void* s2,int size)
{
	for (int i = 0; i < size; i++)
	{
		char c = 0;
		c = *((char*)s1+i);
		*((char*)s1+i) = *((char*)s2+i);
		*((char*)s2+i) = c;
	}
}

void bubbleSort(void* s, int sz,int size,int(*cmp)(const void*e1,const void*e2))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			//如果比较方法(函数)返回的值大于0,就进行交换
			if (cmp(((char*)s + size*j), ((char*)s + size*(j+1)))>0)
			{
				//进行交换
				swap(((char*)s + size * j), ((char*)s + size * (j + 1)),size);
			}
		}
	}
}

//进行测试
void text1()
{
	int a[7] = { 0,1,8,4,6,3,5 };
	int sz = sizeof(a) / sizeof(a[0]);
	bubbleSort(a, sz, sizeof(a[0]), cmp_int);
	for (int i = 0; i < sz; i++)
		printf("%d ", a[i]);

	char str[4] = "aBDA";
	int sz = sizeof(str) / sizeof(str[0]);
	bubbleSort(str, sz, sizeof(str[0]), cmp_char);
	for (int i = 0; i < sz; i++)
		printf("%c ", str[i]);

	struct stu s1[] = {
   
   {"zhangsan",30},{"lisi",16} ,{"wangwu",26}};
	int sz = sizeof(s1) / sizeof(s1[0]);
	bubbleSort(s1, sz, sizeof(s1[0]), cmp_stu_name);
	for (int i = 0; i < sz; i++)
		printf("%s %d", s1[i].name, s1[i].age);
}

int main()
{
	text1();
	return 0;
}

Eight: Conclusion

So far we have completed the simulation implementation of the qsort() function. You can also design more comparison methods (functions) according to your own needs. I believe that you have a clearer understanding of pointer functions and callback functions, and I hope you can comment Point out my shortcomings, let us make progress together, end!

Guess you like

Origin blog.csdn.net/2301_76269963/article/details/129498805