2015-09-27 109 views
2

我在C中对dirent结构进行排序时遇到了问题。我尝试了所有内容,无法获取我的结构数组的值以显示在我的比较中。我的代码如下所示:无法使用qsort在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是不是一个好的解决方案。有人知道像这样的数组的正确大小吗?

UPDATE 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 
} 
+0

这一行:'file_list [count] = sd;'只复制一个指针。你实际需要的东西类似于:'memcpy(file_list [0],sd,sizeof(struct dirent));' – user3629249

+0

你不需要转换'void *'。 –

+0

@ user3629249的确,这段代码泄漏了内存。不仅如此,当OP取消引用时,'closedir()'将释放所有指向数组中悬挂指针的指针,并导致*未定义的行为。虽然代码中没有'closedir()',这意味着有另一个内存泄漏。 –

回答

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); 
    

    是错误的,试图打印的价值,看到它应该是

    file_list_size = count; 
    

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

    由于file_list是指向指针的指针,即不是阵列,那么结果

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

    是不是你认为它是什么或它实际应该是什么。

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

另外:

  • 您的代码泄漏为this comment

  • 指出了@user3629249你不需要cast the return value from 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; 
} 

记住的count值限制为您分配的空间指针的最大数量的例子。

+0

我已经添加了您提到的行,但first_dirent的值为NULL。我似乎有一个问题,传递到比较函数 – VMA92

+0

值的大小。我会尝试数数,看看如何。 – VMA92

+0

@ VMA92请将'readdir()'循环限制为'5'(与'malloc(5 * sizeof(struct dirent *))'同时测试,否则无法预测程序的结果。另外,你使用'malloc()'并且使用'dirent'而不使用'struct'建议你使用一个C++编译器。如果这是真的,请重新回答你的问题并让我删除答案,因为C++程序员不会使用这个函数来完成这个任务。 –

3

您的sizeCompare函数没有返回任何东西。你需要实现的是当它返回-1时a < b,0时a = b和1时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); 
+0

是的我知道,我的问题是更多的是,它不是打印任何告诉我的值传递到A和B是空的这是我的主要问题 – VMA92

+0

也许错误是在计算'file_list_size'。 'sizeof(&file_list)'的价值是什么? –

+0

我得到sizeof(&file_list)的值为 – VMA92

相关问题