Advanced pointer

After we have learned the type of pointer, we think about how to apply it.

Let's look at the code last time

void menu()
{
	printf("*******1.Add         ************\n");
	printf("*******   2.Sub      ************\n");
	printf("*********3.Mul       *************\n");
	printf("***********4.Div     *************\n");
	printf("***********0.exit    *************\n");

}


int main()
{
	int choose = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		menu();
		printf("Please select\n");
		scanf("%d", &choose);
		switch (choose)
		{
		case 1:
			printf("Please enter two operands:>");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("ret = %d\n", ret);
			break;
		case 2:
			printf("Please enter two operands:>");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("ret = %d\n", ret);
			break;
		case 3:
			printf("Please enter two operands:>");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("ret = %d\n", ret);
			break;
		case 4:
			printf("Please enter two operands:>");
			scanf("%d %d", &x, &y);
			ret = Div(x, y);
			printf("ret = %d\n", ret);
			break;
		case 0:
			printf("End exit\n");
		default:
			printf("Please input again!");

		}
	} while (choose);
	return 0;
}

In fact, such code is very redundant, and the right things are repeated.

But we can reduce repetition by using pointer functions.

void menu()
{
	printf("*******1.Add         ************\n");
	printf("*******   2.Sub      ************\n");
	printf("*********3.Mul       *************\n");
	printf("***********4.Div     *************\n");
	printf("***********0.exit    *************\n");

}


void calc(int (*p)(int, int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("Please enter two operands:>");
	scanf("%d %d", &x, &y);
	ret = (*p)(x, y);
	printf("%d\n", ret);
}

int main()
{
	int choose = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		menu();
		printf("Please select\n");
		scanf("%d", &choose);
		switch (choose)
		{
		case 1:
			calc(Add);

			break;
		case 2:
			calc(Sub);

			break;
		case 3:

			calc(Mul);
			break;
		case 4:

			calc(Div);
			break;
		case 0:
			printf("End exit\n");
		default:
			printf("Input error, please re-enter!");

		}
	} while (choose);
	return 0;
}

So we can reduce duplication.

In fact, this is the callback function

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

Next, let's talk about another case.

We should still remember the bubble sort before.

void bubble_sort(int arr[], int sz)
{
	int i = 0;

	for (i = 0; i < sz-1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j+1] < arr[j])
			{
				int tem = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tem;
			}
		}
	}
}
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);
	int i = 0;
	for (i = 0; i < sz ; i++)
	{
		printf("%d ",arr[i]);
	}
	return 0;
}

We all know that bubble sorting can be used for arrays of type int, but if I want to sort characters and strings, can I find a function to sort?

Here, we need to understand the qsort function.

Here are four parameters,

The first is a pointer to void *, the second and third are pointers of type int, and the fourth is a function pointer

This cdecl takes two const void * pointers as parameters.

Where base is the beginning of the starting position, which is the address of the first element of the array

The second num is the number to be sorted,

The third width is the width, the number of bytes of a single element of the array.

The fourth function pointer is a comparison function.

Here we look at the return type requirements of this function pointer.

Let's think about the disadvantages of bubble sorting. If I want to sort, it doesn't have to be compared according to the int type. If I want to compare strings, bubble sorting can't accomplish what we want.

Let's take another look at qsort sorting. The base is void * typeless. In this way, we know that qsort must solve the problem of string sorting.

Let's first think about the implementation of the comparison function cdecl.

First, let's look at untyped pointers.

Pointer variables without specific types can store addresses of any type. So we all use void * type to accept.

When sorting, we may sort character arrays, floating-point arrays and integer arrays. If we write the function type dead at the beginning, we cannot sort.

However, pointers of void * type cannot be dereferenced directly.

At the same time, for pointers of void * type, there is no way to use + +, or --;

You must cast it before you can do this.

Therefore, the function can be written as follows:

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

However, special attention should be paid to the type of floating-point type here, because when 0.9-0.1 occurs, the function returns an integer, that is, it returns 0; Therefore, when there is a floating-point type, we only use the judgment size of if else if to return.

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
struct Stu
{
	char name[20];
	int age;
	float score;
};
int cmp_stu_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int cmp_Stu_by_name(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->name - ((struct Stu*)e2)->name;
}
int cmp_stu_by_score(const void* e1, const void* e2)
{
	if (((struct Stu*)e1)->age > ((struct Stu*)e2)->age)
	{
		return 1;
	}
	else if (((struct Stu*)e1)->age < ((struct Stu*)e2)->age)
		return -1;
	else
		return 0;
}
void my_printf(struct Stu arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d %f\n", arr[i].name, arr[i].age, arr[i].score);
	}
}
void text2()
{
	struct Stu arr[] = { {"zhangsan",20,87.5f},{"lisi",22,99.0f},{"wangwu",10,68.5f} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
	my_printf(arr, sz);
}
int main()
{
	text2();
	return 0;
}

This is to use the method of qsort to write a function to compare the size of two elements, and then pass this function to qsort so that we can sort.

Now that we have realized and understood the elements of qsort, we still can't understand the specific implementation steps of qsort, but we have also learned a sort before.

It's called bubbling sort. Can we use bubbling sort to realize the characteristics similar to qsort sort.

int cmp(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 tem = *buf1;
		*buf1 = *buf2;
		*buf2 = tem;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const 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)
			{
				swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

void my_printf(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

void text3()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp);
	my_printf(arr, sz);
}


int main()
{
	text3();

	return 0;
}

Keywords: C

Added by OnePlus on Wed, 02 Mar 2022 12:57:30 +0200