qsort库函数和函数指针

本文详细介绍了C语言中的qsort函数使用方法及其参数意义,包括如何定义比较函数以实现不同数据类型的排序,并提供了多个排序示例,如整数数组、字符数组及结构体数组的排序。

c语言快速排序库函数qsort:

在C语言的定义中,我们可以看到他的函数原型

void qsort( void * Base,int nelem, unsigned int width, in (* PfCompare)(const void , const void ));

此函数可对任意类型的数组进行排序

这个函数对数组排序时需要知道:

  1. .数组起始的地址
  2. 数组元素的个数
  3. 每个元素的大小
  4. 元素的排序规则

代码中每个单词的含义:
base:待排序数组地址的起始地址
nelem:待排序数组的元素个数
width:每个元素的大小
pfcompare:比较函数的地址(该比较函数需自己编写规则)

ps:pf函数形式:int 函数名(const void * elem1,const void* elem2)

排序就是一个不断比较并交换位置的过程。

qsort函数在执行期间,会通过pfcompare指针调用“比较函数”,
调用时将要比较的两个元素的地址传给“比较函数”,然后根据
“比较函数”返回值判断两个元素哪个更应该排在前面。

这里写图片描述

比较函数的编写规则:

  1. 如果*elem1应该排在*elem2前面,则函数返回值是负整数
  2. 如果*elem1和*elem2Negev排在前面都行,那么返回值0
  3. 如果*elem1应该排在*elem2垢面,则函数返回值是正整数

实例:
下面的程序,功能是调用qsort函数,将一个unsigned int数组按照个位数从小到大进行排序。比如8,23,15三个数,
按个位数从小到大排序,应该是23,15,8

#include<stdio.h>
#include<stdlib.h>
int mycompare(const void* elem1,const void* elem2)
{
    unsigned int* p1,*p2;
    p1=(unsigned int*)elem1;//"*elem1"非法
    p2=(unsigned int*)elem2;
    return (*p1%10)-(*p2%10);
}
#define NUM 5
int main()
{
    unsigned int a[NUM]={8,123,11,10,4};
    qsort(a,NUM,sizeof(unsigend int),mycompare);
    for(int i=0;i<NUM;i++)
        printf("%d",a[i]);
    return 0;
}

输出结果 10 11 123 4 8

如果自己写一个通用的快排函数:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct S
{
    char name[10];
    float score;
}stu;
int cmp(const void*n1, const void*n2)
{
    return *(int*)n1 - *(int*)n2;
}
int struct_cmp(const void *elem1, const void *elem2)
{
    return (*(stu *)elem1).score - (*(stu *)elem2).score;
}
int str_cmp(const void *elem1, const void *elem2)
{
    return strcmp((char *)*(int *)elem1, (char *)*(int *)elem2);
}
void swap(char *buf1, char* buf2, int width)
{
    int i = 0;
    for (i = 0; i < width; i++)
    {
        char tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}
void bubble_sort(void *base, int len, int width, int(*cmp)(const void* n1, const void*n2))
{
    int i = 0;
    for (i = 0; i < len - 1; i++)
    {
        int j = 0;
        for (j = 0; j < len - 1 - i; j++)
        {
            int ret = cmp(((char*)base + (j*width)), ((char*)base + (j + 1)*width));
            if (ret>0)
            {
                swap(((char*)base + (j*width)), ((char*)base + (j + 1)*width), width);
            }
        }
    }
}
int main()
{
    int arr[] = { 8, 5, 6, 1, 2, 3, 4 };
    int len = sizeof(arr) / sizeof(arr[0]);
    bubble_sort(arr, len, sizeof(arr[0]), cmp);
    int i = 0;
    for (i = 0; i <len; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
    char arr1[] = { 'f', 'h', 'm', 'l', 'g', 'k', 'c' };
    int len1 = sizeof(arr1) / sizeof(arr1[0]);
    bubble_sort(arr1, len1, sizeof(arr1[0]), cmp);
    for (i = 0; i < len1; i++)
    {
        printf("%c ", arr1[i]);
    }
    printf("\n");
    stu arr2[] = { { "aa", 9}, { "bb", 6}, { "cc", 8}, { "dd", 7} };
    int len2 = sizeof(arr2) / sizeof(arr2[0]);
    bubble_sort(arr2, len2, sizeof(stu), struct_cmp);
    for (i = 0; i < len2; i++)
    {
        printf("%s %f ", arr2[i].name, arr2[i].score);
    }
    printf("\n");
    char *arr3[] = { "aaa", "dddd", "cccc", "bbbb" };
    int len3 = sizeof(arr3) / sizeof(arr3[0]);
    bubble_sort(arr3, len3, sizeof(char *), str_cmp);
    for (i = 0; i < len3; i++)
    {
        printf("%s ", arr3[i]);
    }
    printf("\n");
    system("pause");
    return 0;
}
### C/C++ 中函数指针的概念 在 C C++ 编程语言中,函数指针是一种特殊的指针类型,用于存储函数的入口地址。通过这种机制,程序员可以通过指针间接调用函数[^4]。 #### 函数指针的作用 函数指针的主要作用在于提供一种灵活的方式来动态决定执行哪个函数。它允许将函数作为参数传递给其他函数,或者返回某个特定的函数地址以便稍后调用。这使得程序设计更加模块化可扩展[^1]。 --- ### 函数指针的定义与语法 函数指针的定义遵循一定的语法规则。以下是其基本形式: ```cpp return_type (*pointer_name)(parameter_list); ``` 其中: - `return_type` 是被指向函数的返回值类型; - `(*pointer_name)` 表示这是一个指针变量名; - `(parameter_list)` 列出了目标函数所需的参数列表。 例如,在 C++ 中可以这样声明一个函数指针: ```cpp void (*funcPtr)(int); // 声明了一个名为 funcPtr 的函数指针,它可以指向接受单个整数参数并返回 void 类型的函数。 ``` --- ### 函数指针的使用方法 为了更好地理解函数指针的实际应用,以下是一些常见的场景及其对应的代码示例。 #### 示例 1:简单函数指针的声明与初始化 考虑如下代码片段,展示了如何声明、初始化以及调用一个函数指针[^2]: ```cpp #include <iostream> // 定义一个函数 void PrintNumber(int num) { std::cout << "Number: " << num << std::endl; } int main() { // 声明并初始化函数指针 void (*funcPtr)(int) = PrintNumber; // 使用函数指针调用函数 funcPtr(42); return 0; } ``` 上述代码中,`PrintNumber` 函数被分配给了函数指针 `funcPtr`,随后通过该指针成功调用了原函数。 --- #### 示例 2:函数指针数组的应用 如果需要管理多个具有相同签名的函数,则可以利用函数指针数组简化操作。例如: ```cpp #include <iostream> using namespace std; // 不同功能的函数 void FunctionA() { cout << "This is Function A." << endl; } void FunctionB() { cout << "This is Function B." << endl; } int main() { // 创建函数指针数组 void (*functionArray[])(void) = {FunctionA, FunctionB}; // 遍历并调用这些函数 functionArray[0](); functionArray[1](); return 0; } ``` 此例子说明了如何借助函数指针数组统一处理一组相似行为的功能模块。 --- #### 示例 3:回调函数中的函数指针 另一个典型用途是在事件驱动编程模型下充当 **回调函数** 参数的角色。比如下面这段伪代码展示了一种可能的情况[^3]: ```cpp #include <stdio.h> typedef int (*CompareFunc)(const void *, const void *); int CompareInts(const void *a, const void *b) { return (*(int *)a - *(int *)b); } void Sort(void *base, size_t nmemb, size_t size, CompareFunc cmp) { qsort(base, nmemb, size, cmp); } int main() { int numbers[] = {5, 3, 8, 6}; Sort(numbers, sizeof(numbers)/sizeof(numbers[0]), sizeof(int), CompareInts); for (size_t i = 0; i < sizeof(numbers)/sizeof(numbers[0]); ++i) printf("%d ", numbers[i]); return 0; } ``` 在这里,标准库函数 `qsort()` 接受自定义比较逻辑作为最后一个参数——即由用户提供的函数指针完成排序规则定制。 --- ### 总结 综上所述,函数指针不仅增强了 C/C++ 程序员控制流的能力,还促进了软件组件之间的解耦合程度。无论是构建复杂的算法框架还是实现高效的运行时决策结构,都离不开这一强大工具的支持。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值