[Langage C] Fonction de rappel, utilisation de la fonction de tri qsort et de sa propre implémentation, explication super détaillée


insérez la description de l'image ici
Premier record que le nombre de visites a dépassé les 2000, merci pour votre soutien ! ! !
Voici le lien avancé du pointeur précédent, qui est pratique pour tout le monde : Ajouter une description du lien

avant-propos

Bonjour à tous, aujourd'hui je voudrais partager le reste du contenu du dernier numéro de pointeurs avancés - la fonction de rappel, c'est très important, apprenons à le comprendre ensemble ! ! !


1. Quelle est la fonction de rappel

Concept standard :
une fonction de rappel est une fonction appelée via un pointeur de fonction. Si vous passez un pointeur de fonction (adresse) en paramètre à une autre
fonction, lorsque ce pointeur est utilisé pour appeler la fonction vers laquelle il pointe, nous disons qu'il s'agit d'une fonction de rappel. La fonction de rappel n'est pas
directement appelée par l'implémenteur de la fonction, mais est appelée par une autre partie lorsqu'un événement ou une condition spécifique se produit, et est utilisée pour répondre à l'événement ou à la condition
.

En termes simples : une fonction appelée par un pointeur de fonction dans une autre fonction est appelée une fonction de rappel

Deuxièmement, l'utilisation de la fonction de rappel

1. Utilisez la fonction qsort dans la bibliothèque standard

La fonction qsort peut non seulement trier des tableaux d'entiers, mais aussi trier des types de données tels que des structures

code afficher comme ci-dessous:

#include <stdio.h>
//qosrt函数的使用者得实现一个比较函数
int int_cmp(const void * p1, const void * p2)
{
    
    
  return (*( int *)p1 - *(int *) p2);
}//这里必须有使用者根据自己的排序依据自己写的比较函数

int main()
{
    
    
    int arr[] = {
    
     1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
    int i = 0;
    
    qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
    //qsort的第一个参数是排序数组的首元素地址
    //第二个参数是排序的长度
    //第三个参数是每个元素的大小
    //第四参数是使用者自己写的排序依据函数的地址(这里就是使用回调函数)
    for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
   {
    
    
       printf( "%d ", arr[i]);
   }
    printf("\n");
    return 0;
}

L'affichage du résultat courant du tri des tableaux d'entiers :
insérez la description de l'image ici

2. Utilisez la fonction qsort pour trier le tableau de structure

Regardez d'abord le code comme suit:

#include<stdio.h>
#inlcude<string.h>
struct stu {
    
    
	int age;
	char name[20];
	double score;
};
//依据年龄大小排序的比较函数
int compar_by_age(const void* e1, const void* e2)
{
    
    
	return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
//依据名字排序的比较函数
int compar_by_name(const void* e1, const void* e2)
{
    
    
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
int main()
{
    
    
//这是定义一个结构体类型的数组
	struct stu S[3] = {
    
     {
    
    21,"FRH",100},{
    
    19,"MSY",90},{
    
    18,"LZY",85} };
	int Ssz = sizeof(S) / sizeof(S[0]);
	qsort(S, Ssz, sizeof(S[0]), compar_by_age);
	qsort(S, Ssz, sizeof(S[0]), compar_by_name);
	return 0;
}

Comparaison des résultats avant et après tri :
C'est l'ordre du tableau de structure avant tri :
insérez la description de l'image ici
C'est l'ordre après tri par âge :
insérez la description de l'image ici
C'est l'ordre après tri par nom :
insérez la description de l'image ici

Troisièmement, réalisez la fonction qsort

Voyons d'abord l'apparence de la fonction qsort dans la bibliothèque standard :
insérez la description de l'image ici
elle n'a pas de valeur de retour, et les quatre paramètres sont :
1. Le premier paramètre de qsort est l'adresse du premier élément du tableau trié
2. Le le deuxième paramètre est la longueur du tri
3. Le troisième paramètre est la taille de chaque élément
4. Le quatrième paramètre est l'adresse de la fonction de tri écrite par l'utilisateur (ici la fonction callback)

作者是依据冒泡排序实现的qosrt函数,我们之间上代码:
#include<stdio.h>
#inlcude<string.h>
//依据名字排序的比较函数
int compar_by_name(const void* e1, const void* e2)
{
    
    
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
//依据整型大小排序的比较函数
int int_cmp(const void * p1, const void * p2)
{
    
    //这里都会将接收到的地址转换为所需要比较的类型
  return (*( int *)p1 - *(int *) p2);
}

//这里排序中交换两个元素的交换函数
void Swap(char* x, char* y,int size)
{
    
    
//利用char* 接收需要交换的元素,可以保证对其每个字节进行交换从而实现整体全部字节的交换
//size就是该元素所占字节的大小,决定每次交换循环几次
	int i = 0;
	for (i = 0; i < size; i++)
	{
    
    
		char temp = *x;
		*x = *y;
		*y = temp;
		x++;
		y++;

	}
}

void Bubble_Sort(void* base, size_t num, size_t size,int (*compar)(const void*, const void*))
{
    
    
	int i = 0;
	for (i = 0; i < num - 1; i++)
	{
    
    
		int j = 0;
		for (j = 0; j < num - 1 - i; j++)
		{
    
    
		//为什么要将首元素地址转换为char* 类型呢?
		//因为:这样可以保证任何类型数组在排序比较时能够访问到其中的每一个元素
		//这个设计是真的巧妙
			if (compar(((char*)base + j * size), ((char*)base + (j+1)*size))>0)
			{
    
    
				Swap(((char*)base + j * size), ((char*)base + (j+1)*size), size);
			}
		}
	}
}

Testez-le :

int main()
{
    
    
	int arr[10] = {
    
     9,8,7,6,5,4,3,2,1,0 };
	struct stu S[3] = {
    
     {
    
    21,"FRH",100},{
    
    19,"MSY",90},{
    
    18,"LZY",85} };
	int Ssz = sizeof(S) / sizeof(S[0]);
	int sz = sizeof(arr) / sizeof(arr[0]);
	Bubble_Sort(arr,sz,sizeof(arr[0]),compar_by_int);
	Print(arr, sz);
	Bubble_Sort(S, Ssz, sizeof(S[0]), compar_by_age);
	Bubble_Sort(S, Ssz, sizeof(S[0]), compar_by_name);
	return 0;
}

On peut obtenir que le résultat du tri est le même que le résultat de l'appel de la fonction qsort dans la bibliothèque d'annotations ci-dessus
insérez la description de l'image ici

Résumer

C'est la fin du partage de la fonction de rappel. J'espère que la fonction qsort pourra aider tout le monde. Le blogueur pense qu'elle est vraiment utile. Je l'utiliserai le plus possible à l'avenir. J'espère que cet article pourra aider tout le monde . Merci pour la lecture! ! !

Je suppose que tu aimes

Origine blog.csdn.net/m0_71214261/article/details/132272332
conseillé
Classement