之前一直用qsort对整型数组进行排序,qsort同样可以对字符数组排序。但是这次对字符串指针数组排序,属实是绕了一会,记录一下。


前言

qsort排序


一、字符型指针数组排序

1、qsort头文件

#include <stdlib.h>

2、qsort 写法

void qsort (void *base, size_t nitems, size_t size, int (*compar) (const void *, const void*)) 

3、对字符型指针数组进行排序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define STRING_COUNT   4

int comp(const void* a, const void* b)
{
    int diff = strcmp((char*)((int*)(*(int*)a)) , (char*)((int*)(*(int*)b)));
    return diff;
}

int main()
{
    char *p[STRING_COUNT];
    for(int i = 0; i < STRING_COUNT; i++)
    {
        p[i] = (char*)malloc(sizeof(char) * 10);
    }
    p[0] = "hello!";
    p[1] = "world";
    p[2] = "test";
    p[3] = "goodbye";

    qsort(p, STRING_COUNT, sizeof(char*), comp);
    for(int i = 0; i < STRING_COUNT; i++)
    {
        printf("%s\n", p[i]);
    }
}

//goodbye
//hello!
//test
//world

过程中也是调试了很多次! 

理解为qsort将指针数组的成员,即指针传给comp函数,comp的形参接受的是指针数组的成员。这个成员对应的是char型数组的地址。所以形参是地址。地址要看成是int型,强制类型转换成int型,再将常量强制转换成地址的方式(unsigned int*)转成地址类型,即可以解析出char型字符串。

作为strcmp的参数还有再转成(char*)。

另外qsort(p, STRING_COUNT, sizeof(char*), comp);这边要这样写。

3.2 更新

2024年4月1日10:44:44

这两天由于写牛客的题目,重新联系到qsort用法以及对字符串数组排序的问题,这边对上述字符串指针数组排序的代码重新梳理一遍。对于上面第一版的代码,肯定是有问题的。下面是新修改的代码

第一版百思不解版

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define STRING_COUNT   4

int comp(const void* a, const void* b)
{
    int diff = strcmp( (char*)(*((char*)a)), (char*)(*((char*)b)) );
    return diff;
}

int main()
{
    char *p[STRING_COUNT];
    for(int i = 0; i < STRING_COUNT; i++)
    {
        p[i] = (char*)malloc(sizeof(char) * 10);
    }
    p[0] = "hello!";
    p[1] = "world";
    p[2] = "test";
    p[3] = "goodbye";

    qsort(p, STRING_COUNT, sizeof(char*), comp);
    for(int i = 0; i < STRING_COUNT; i++)
    {
        printf("%s\n", p[i]);
    }
}

上述代码一通尝试没有实现效果,根本不知道问题出在哪里,最后还是百度得到了正确的处理方法,见下面的代码。 

第二版成功版

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define STRING_COUNT   4

int comp(const void* a, const void* b)
{
    int diff = strcmp( (*(char**)a), (*(char**)b) );            //实参是指针数组,形参变成了二级指针。这边先由void*强转成原二级指针类型。再解引用使用,成功
    return diff;
}

int main()
{
    char *p[STRING_COUNT];
    for(int i = 0; i < STRING_COUNT; i++)
    {
        p[i] = (char*)malloc(sizeof(char) * 10);
    }
    p[0] = "hello!";
    p[1] = "world";
    p[2] = "test";
    p[3] = "goodbye";

    qsort(p, STRING_COUNT, sizeof(char*), comp);
    for(int i = 0; i < STRING_COUNT; i++)
    {
        printf("%s\n", p[i]);
    }
}

//goodbye
//hello!
//test
//world

参考自帖子:

HJ27 查找兄弟单词-CSDN博客

 浅学指针(4)函数指针数组和qsort的使用-CSDN博客

4、关于qsort第三个参数的疑虑

根据帖子的解释,第二个参数是数组元素的个数,第三个参数是数组元素的大小。

 那么对于HJ27代码,传参形式是sizeof(*dstStrArray),dstStrArray是静态二维数组,sizeof(*dstStrArray)是数组长度11。上面的代码中传参是sizeof(char*),第一个参数str是动态二维数组。sizeof(char*)的值是4。为什么会出现这种不同的传参实参呢?

又联系到结构体数组传参第三个参数是结构体大小。所以目前这样认为,第三个参数是数组元素大小。至于如果数组元素是指针,那么要做强制类型转换,转换成原数组类型,再做处理。HJ27的参数也是指针。。

额,这边好像又乱了,先这样吧。

遗留问题:

1、第三参数传参问题。

2、指针指向数组,sizeof问题

3、函数指针数组问题

2024年7月25日16:13:20

今天突然又想到qsort用法,尤其是对字符串数组的排序。看了这篇文章:

[关于C语言qsort函数详解](关于C语言qsort函数详解_C 语言_脚本之家)

然后又看了这篇文章,我已经有了正确的答案。

今天在刷题,oj工号整理的题目,遇到字符串数组排序,又把自己搞懵逼了,原题不写了,只写自己遇到问题后写的测试代码,实际上测试代码也有问题。还是看了这篇帖子才搞对。再记录一下。

下面是测试验证代码

int compareError(const void *a, const void *b)
{
    return strcmp((char*)a , (char*)b);
}

int compare(const void *a, const void *b)
{
    return strcmp(*(char**)a , *(char**)b);
}


void test()
{
    char array1[10] = "zzzzzzzzz";
    char array2[10] = "zzzzzzzzz";
    char array3[10] = "s00000123";
    char array4[10] = "k00023490";
    char array5[10] = "zzzzzzzzz";
    char array6[10] = "s00000234";
    char array7[10] = "x00000235";
    char array8[10] = "m00000990";
    char* array[8];
    array[0] = array1;
    array[1] = array2;
    array[2] = array3;
    array[3] = array4;
    array[4] = array5;
    array[5] = array6;
    array[6] = array7;
    array[7] = array8;
    qsort(array, 8, sizeof(array[0]), compare);
    for(int i = 0; i < 8; i++)
    {
        printf("%s\n", array[i]);
    }

    printf("\n");
    char arrayTemp3[10] = "s00000123";
    char arrayTemp4[10] = "k00023490";
    char arrayTemp6[10] = "s00000234";
    char arrayTemp7[10] = "x00000235";
    char arrayTemp8[10] = "m00000990";
    char* arrayTemp[5];
    arrayTemp[0] = arrayTemp3;
    arrayTemp[1] = arrayTemp4;
    arrayTemp[2] = arrayTemp6;
    arrayTemp[3] = arrayTemp7;
    arrayTemp[4] = arrayTemp8;

    qsort(arrayTemp, 5, sizeof(arrayTemp[0]), compare);
    for(int i = 0; i < 5; i++)
    {
        printf("%s\n", arrayTemp[i]);
    }

    printf("\n");
    char **listDir = (char**)malloc(5 * sizeof(char*));
    for(int i = 0; i < 5; i++)
    {
        listDir[i] = (char*)malloc(sizeof(char) * 10);
        memset(listDir[i], '\0', sizeof(char) * 10);
    }


    memcpy(listDir[0], "s00000123", sizeof(char) * (10));
    memcpy(listDir[1], "k00023490", sizeof(char) * (10));
    memcpy(listDir[2], "s00000234", sizeof(char) * (10));
    memcpy(listDir[3], "x00000235", sizeof(char) * (10));
    memcpy(listDir[4], "m00000990", sizeof(char) * (10));
    qsort(listDir, 5, sizeof(listDir[0]), compare);
    for(int i = 0; i < 5; i++)
    {
        printf("%s\n", listDir[i]);
    }

}

还是要理解指针啊。。。


总结

后面可以回顾一下。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐