欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語(yǔ)言中回調(diào)函數(shù)和qsort函數(shù)的用法詳解

 更新時(shí)間:2022年07月18日 09:24:50   作者:從未止步..  
這篇文章主要為大家詳細(xì)介紹一下C語(yǔ)言中回調(diào)函數(shù)和qsort函數(shù)的用法教程,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語(yǔ)言有一定幫助,需要的可以參考一下

回調(diào)函數(shù)

通過(guò)函數(shù)指針調(diào)用的函數(shù),如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來(lái)調(diào)用其所指向的函數(shù)時(shí),我們就說(shuō)這是回調(diào)函數(shù)。

回調(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用的,用于對(duì)該事件或條件進(jìn)行響應(yīng)。

舉例:

#include<stdio.h>
void menu()
{
    printf("********************************\n");
    printf("**    1.and        2.sub      **\n");
    printf("**    3.mul        4.div      **\n");
    printf("********************************\n");
}
int add(int x, int y)
{
    int z = 0;
    z = x + y;
    return z;
}
int sub(int x, int y)
{
    int z = 0;
    z = x - y;
    return z;
}
int mul(int x, int y)
{
    int z = 0;
    z = x * y;
    return z;
}
int div(int x, int y)
{
    int z = 0;
    z = x / y;
    return z;
}
void Calc(int(*pf)(int, int))//int(*pf)(int, int)等于add,只不過(guò)選用不同的方式進(jìn)行調(diào)用
{
    int x = 0;
    int y = 0;
    printf("請(qǐng)輸入兩個(gè)操作數(shù):>");
    scanf_s("%d%d", &x, &y);
    printf("%d\n", pf(x, y));//通過(guò)指針對(duì)add函數(shù)進(jìn)行調(diào)用,而不是像之前那樣使用函數(shù)名進(jìn)行調(diào)用
}
int main()
{
    int input = 0;
    do
    {
        menu();
        printf("請(qǐng)選擇:>");
        scanf_s("%d", &input);
        switch (input)
        {
        case 1:
            Calc(add);//將add函數(shù)的地址傳遞過(guò)去,這里的add函數(shù)為回調(diào)函數(shù)
            break;
        case 2:
            Calc(sub);
        case 3:
            Calc(mul);
        case 4:
            Calc(div);

        }
    } while (input);
}

指向函數(shù)指針數(shù)組的指針

指向函數(shù)指針數(shù)組的指針是一個(gè)指針,指向一個(gè)數(shù)組,數(shù)組的元素都是函數(shù)指針;

如何定義?

    int arr[10] = { 0 };//整型數(shù)組
    int(*p)[10] = &arr;//取出數(shù)組的地址
    int (*pf)(int, int);//函數(shù)指針
    int(*pfarr[4])(int, int);//pfarr是一個(gè)數(shù)組,函數(shù)指針的數(shù)組
    int(*(*ppfarr)[4])(int, int) = &pfarr;//ppfarr指向函數(shù)指針數(shù)組的指針
    //pfarr是一個(gè)數(shù)組指針,指針指向的數(shù)組有4個(gè)元素
    //指向的數(shù)組的每個(gè)元素的類型是函數(shù)指針int(*)(int,int)

void*

可以用來(lái)接收任何類型數(shù)據(jù)的地址,別名萬(wàn)能指針

既然可以存放任何類型的地址,那么是不是也可以解引用訪問(wèn)存放的值?

下面我們通過(guò)示例:

#include<stdio.h>
int main()
{
    int a = 10;
    void* p = &a;
    printf("%d\n", *p);
}

通過(guò)輸出結(jié)果我們發(fā)現(xiàn),程序并沒(méi)有被正確的運(yùn)行,而是告訴我們,我們進(jìn)行了非法間接尋址。

那么為什么會(huì)出現(xiàn)這樣的現(xiàn)象呢?

原因是void*雖然可以接受任意類型的地址,但它自己本身的類型是空類型,那么在解引用操作的時(shí)候,系統(tǒng)并不知道它的類型,因此不知道需要分配給其幾個(gè)字節(jié),指針類型決定了它的字節(jié)大小。

因此,void*不能進(jìn)行解引用操作

那么可以進(jìn)行++/–操作嗎?

我們通過(guò)實(shí)例進(jìn)行驗(yàn)證一下:

#include<stdio.h>
int main()
{
    int a = 10;
    void* p = &a;
    p++;
}

程序依然沒(méi)有正確運(yùn)行,編譯器指出了錯(cuò)誤的原因:void未知的大小,和上面一樣的道理,我們并不清楚此時(shí)存放在void里面的數(shù)據(jù)是什么類型,自然也不知道它所占據(jù)內(nèi)存空間的大小,因此步長(zhǎng)是無(wú)法確定的。

因此void*也不可以進(jìn)行++/–操作

qsort(qulick sort)-庫(kù)函數(shù)

適用的場(chǎng)景:適用于對(duì)某一組數(shù)據(jù)進(jìn)行快速排序

qsort(s,sz,sizeof(s[0]),cmp_stu_by_name);
//第一個(gè)參數(shù)s:待排序數(shù)組的首元素地址
//第二個(gè)參數(shù)sz:待排序數(shù)組的元素個(gè)數(shù)
//第三個(gè)參數(shù)sizeof(s[0]):待排序數(shù)組的每個(gè)元素的大小,單位是字節(jié)
//第四個(gè)參數(shù):是函數(shù)指針,比較兩個(gè)元素的所用函數(shù)的地址
//這個(gè)函數(shù)使用者自己實(shí)現(xiàn)函數(shù)指針的兩個(gè)參數(shù)是:待比較的兩個(gè)元素的地址

舉例:

常規(guī)方法:冒泡排序:

#include<stdio.h>
int main()
{
    int arr[10] = { 9,2,3,1,4,5,7,6,0,91 };
    int i, j=0,temp;
    int sz = sizeof(arr) / sizeof(arr[0]);
    for (i = 0; i < sz-1; i++)//決定需要比較多少次
    {
        for (j=0; j < sz-1-i; j++)
        {
            if (arr[j+1] > arr[j])
            {
                temp = arr[j+1];
                arr[j+1] = arr[j];
                arr[j] = temp;
            }    
        }
    }
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

輸出:

91 9 7 6 5 4 3 2 1 0

但是,這種方法的局限性非常大,執(zhí)行效率也不高。

因此在進(jìn)行數(shù)據(jù)類型的排序問(wèn)題時(shí),我們可以選擇qsort函數(shù):

下面我們就來(lái)學(xué)習(xí)qsort函數(shù):

//int (*cmp)(const void *,const void *);
qsort(*s, n, sizeof(s[0]), cmp);

其中第一個(gè)參數(shù)s是一個(gè)地址,即參與排序的首地址; n是需要排序的數(shù)量; sizeof(s[0])則是每一個(gè)元素占用的空間大?。?/p>

指向函數(shù)的指針,用于確定排序的順序。

sz=sizeof(arr)/sizeof(arr[0])
qsort(a, sz,arr[0], cmp);
//其中cmp函數(shù)應(yīng)寫(xiě)為:
int cmp(const void *a, const void *b)//void*可接受任意類型的數(shù)據(jù)
{
    return *(int*)a - *(int*)b; //由小到大排序
    //return *(int *)b - *(int *)a; 由大到小排序
}

對(duì)于整形數(shù)據(jù)的比較實(shí)現(xiàn)過(guò)程:

#include<stdio.h>
#include<stdlib.h>#qsort的頭文件
int cmp_int(const void* e1, const void* e2)//e1和e2是用來(lái)接收要比較的兩個(gè)元素的地址
{
    return *(int*)e1 - *(int*)e2;
}
int main()
{
    int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    qsort(arr,sz, sizeof(arr[0]), cmp_int);
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);//整形打印%d
    }
    return 0;
}

輸出:

0 1 2 3 4 5 6 7 8 9

對(duì)于浮點(diǎn)型數(shù)據(jù)的比較實(shí)現(xiàn)過(guò)程:

int cmp_float(const void* e1, const void* e2)//e1和e2是用來(lái)接收要比較的兩個(gè)元素的地址
//由于cmp_float函數(shù)的返回類型是int,因此,需要進(jìn)行轉(zhuǎn)化
{
     //可用if分支語(yǔ)句
    /*if (*(float*)e1 == *(float*)e2)
        return 0;
    else if (*(float*)e1 > *(float*)e2)
        return 1;
    else
        return 0;*/
        //也可用return直接返回
    return ((int) * (float*)e1 - *(float*)e2);
}
int main()
{
    float f[] = { 9.0,8.0,7.0,6.0,5.0,4.0 };
    int sz = sizeof(f) / sizeof(f[0]);
    qsort(f,sz, sizeof(f[0]), cmp_float);
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%f ", f[i]);//浮點(diǎn)型打印%f
    }
    return 0;
}

對(duì)于結(jié)構(gòu)體類型數(shù)據(jù)的實(shí)現(xiàn)過(guò)程:

結(jié)構(gòu)體類型和整形浮點(diǎn)型在排序的時(shí)候有略微區(qū)別,結(jié)構(gòu)體類型并不能直接進(jìn)行比較,而要按照某一變量,例如:名字,年齡等等

按照年齡比較:

#include<stdio.h>
#include<stdlib.h>
struct stu//定義一個(gè)結(jié)構(gòu)體
{
	char name[20];
	int age;
};

int cmp_s_stu(const void* e1, const void* e2)//e1和e2是用來(lái)接收要比較的兩個(gè)元素的地址
{
	return ((struct stu*)e1)->age - ((struct stu*)e2)->age;//告訴編譯器你想用什么樣的方式進(jìn)行排序
}
int main()
{
	struct stu s[3] = { {"zhangsan",20},{"lisi",30},{"wangwu",10} };
	int sz = sizeof(s) / sizeof(s[0]); 
	qsort(s,sz, sizeof(s[0]), cmp_s_stu);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s ", s[i]);#字符串型,以%s進(jìn)行打印
	}
	return 0;
}

按照名字進(jìn)行比較:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stu
{
	char name[20];
	int age;
};

int cmp_s_stu(const void* e1, const void* e2)//e1和e2是用來(lái)接收要比較的兩個(gè)元素的地址
{
	return strcmp(((struct stu*)e1)->name,((struct stu*)e2)->name);//比較名字就是比較字符串
	//注意字符串在比較大小的時(shí)候,不能直接用加減法進(jìn)行比較,而要用strcmp()函數(shù)
}
int main()
{
	struct stu s[3] = { {"zhangsan",20},{"lisi",30},{"wangwu",10} };
	int sz = sizeof(s) / sizeof(s[0]); 
	qsort(s,sz, sizeof(s[0]), cmp_s_stu);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s ", s[i]);#字符串型,以%s進(jìn)行打印
	}
	return 0;
}

到此這篇關(guān)于C語(yǔ)言中回調(diào)函數(shù)和qsort函數(shù)的用法詳解的文章就介紹到這了,更多相關(guān)C語(yǔ)言 回調(diào)函數(shù) qsort內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論