无法使用C中的qsort对dirent进行排序

时间:2015-09-27 18:49:52

标签: c qsort dirent.h

我无法在C中对dirent结构进行排序。我已经尝试了所有内容,并且无法将我的struct数组的值显示在我的比较中。我的代码如下所示:

void printSortedNames(){

    struct dirent **file_list = (dirent**)malloc(5 * sizeof(dirent*));

    int i = 0;
    for (i = 0; i < directory_size; ++i){
        file_list[i] = (dirent*)malloc(50 * sizeof(dirent));
    }

    DIR *dir;
    struct dirent *sd;

    dir = opendir(".");

    if (dir == NULL){
        printf("Error! unable to open directory.\n");
        exit(1);
    }

    int count = 0;
    while ((sd = readdir(dir)) != NULL){
        file_list[count] = sd;
        printf("%s\n", file_list[count]->d_name);
        ++count;
    }

    size_t file_list_size = sizeof(&file_list) / sizeof(struct dirent);

    qsort(file_list, file_list_size, sizeof(struct dirent), sizeCompare);
}

我创建了一个简单的函数sizeCompare来显示我的函数是否正常工作但我得到了null值。我的功能如下:

int sizeCompare(const void* a, const void* b){

    printf("%s\n", ((const struct dirent*)a)->d_name);
}

有人可以向我解释为什么我的sizeCompare没有正确检索数组值吗?

更新 我试过玩qsort中的大小,结果我的值不再为null。以下行给出了一个输出:

qsort(file_list, 1000, sizeof(struct dirent), sizeCompare);

显然1000不是一个好的解决方案。有没有人知道像这样的数组的正确大小?

更新2: sizeCompare函数只接受第一个参数,第二个参数为null。

int sizeCompare(const void* a, const void* b){

    const struct dirent *first_dirent = *(const struct dirent **) a;
    const struct dirent *second_dirent = *(const struct dirent **) b;
    .......
    //first one works but second one is NULL
}

2 个答案:

答案 0 :(得分:3)

您的sizeCompare函数未返回任何内容。您需要实现的目的是在a < b时返回-1,在a = b时返回0,在a > b时返回1。

int sizeCompare(const void* a, const void* b) {
    // The implementation should return something
}

此外,您正在错误地计算file_list_size。你不能将count作为第二个参数传递吗?

qsort(file_list, count, sizeof(struct dirent), sizeCompare);

答案 1 :(得分:3)

  1. 在比较函数中,您需要通过首先转换为struct dirent **来取消引用指针,就像这样

    const struct dirent *first_dirent = *(const struct dirent **) first_parameter;
    

    这是因为传递了每个元素的地址,因为元素是指针,所以传递给函数的指针是指向指针的指针。他们的void *地址相同,但您无法将const struct dirent **直接投放到const struct dirent *

  2. 你还有另一个重要问题,

    file_list_size = sizeof(&file_list) / sizeof(struct dirent);
    

    是错误的,尝试打印该值并查看它应该是 1

    file_list_size = count;
    

    因为你的代码计算指针的大小除以struct dirent的大小,这可能导致0,读取sizeof运算符,它的结果取决于传递的参数。当它是变量时,类型的大小就是结果,当变量是数组时,它就是数组的大小。

    由于file_list是指向指针的指针,即不是数组,因此是

    的结果
    file_list_size = sizeof(&file_list) / sizeof(struct dirent);
    

    不是您认为的或实际应该是什么。

  3. 没有正确的大小,也许您应该首先计算条目并预测代码中第一个malloc()的值。或者使用realloc()并动态计算条目并同时分配poitners。

  4. 此外:

    • 您的代码在user3629249

    • 中{@ 3}}指出内存泄漏内存
    • 您无需this comment

    • 尽量不要将代码与声明混合,这样就很难跟踪变量及其范围。

    • 您为5个struct dirent *指针分配空间,但是您从不检查计数变量是否达到或超过该值。这可能导致未定义的行为。

    • 您的代码也会泄漏内存,因为您从未致电closedir()

    以下是按字母顺序对条目进行排序的示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <dirent.h>
    
    int
    compareSize(const void *const A, const void *const B)
    {
        return strcmp((*(struct dirent **) A)->d_name, (*(struct dirent **) B)->d_name);
    }
    
    void printSortedNames(const char *const path)
    {
        int count;
        DIR *dir;
        struct dirent **list;
        struct dirent *entry;
    
        dir = opendir(path);
        if (dir == NULL)
        {
            fprintf(stderr, "cannot open `%s'\n", path);
            return;
        }
    
        /* First determine the number of entries */
        count = 0;
        while ((entry = readdir(dir)) != NULL)
            ++count;
        /* Allocate enough space */
        list = malloc(count * sizeof(*list));
        if (list == NULL)
        {
            closedir(dir);
            fprintf(stderr, "memory exhausted.\n");
            return;
        }
        /* You don't need to allocate the list elements
         * you can just store pointers to them in the
         * pointer array `list'
         */
        rewinddir(dir); /* reset position */
        /* Save the pointers allocated by `opendir()' */
        count = 0;
        while ((entry = readdir(dir)) != NULL)
            list[count++] = entry;
        /* Call `qsort()', read about the `sizeof' operator */
        qsort(list, count, sizeof(*list), compareSize);
        /* Print the sorted entries now */
        for (int index = 0 ; index < count ; ++index)
            fprintf(stderr, "%s\n", list[index]->d_name);
        closedir(dir);
    }
    
    int
    main(void)
    {
        printSortedNames("/home/iharob");
        return 0;
    }
    

    1 请记住将count的值限制为为其分配空间的最大指针数。