2

我在 C 中对 dirent 结构进行排序时遇到问题。我已经尝试了所有方法,但无法让我的结构数组的值出现在我的比较中。我的代码如下所示:

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 来显示我的函数正在工作,但我得到了空值。我的功能如下:

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

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

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

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

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

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

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

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
}
4

2 回答 2

4
  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()动态计数条目并同时分配指针。

还:

  • 正如@ user3629249此评论中指出的那样,您的代码泄漏了内存

  • 您不需要malloc()

  • 尽量不要将代码与声明混在一起,这会使跟踪变量及其范围变得困难。

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

  • 您的代码还会泄漏内存,因为您从不调用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您为其分配空间的最大指针数。

于 2015-09-27T19:11:57.833 回答
3

你的sizeCompare函数没有返回任何东西。您需要实现的是它返回 -1 when a < b, 0 whena = b和 1 when a > b

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);
于 2015-09-27T18:54:41.223 回答