无法在 C 中使用 qsort 对 dirent 进行排序
Unable to sort dirent with qsort in C
我在用 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
}
您的 sizeCompare
函数未返回任何内容。您需要实现的是 returns -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);
在比较函数中,您需要通过首先转换为 struct dirent **
来取消引用指针,就像这样
const struct dirent *first_dirent = *(const struct dirent **) first_parameter;
这是因为传递的是每个元素的地址,而元素是指针,所以传递给函数的指针是指向指针的指针。他们的void *
地址是一样的,但是不能直接把const struct dirent **
转成const struct dirent *
.
你还有一个重要的问题,
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);
不是你想的那样,也不是你想的那样。
没有正确的大小,也许您应该先计算条目数并预测代码中第一个 malloc()
的值。或使用realloc()
并动态计算条目并同时分配指针。
还有:
正如@user3629249 in
所指出的那样,您的代码泄漏了内存
你不需要cast the return value from malloc()
尽量不要将代码与声明混在一起,这样很难跟踪变量及其作用域。
您为 5 个 struct dirent *
指针分配了 space,但您从不检查计数变量是否达到或超过该值。这可能会导致未定义的行为。
您的代码也会泄漏内存,因为您从不调用 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
的值限制为你分配的最大指针数space对于.
我在用 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
}
您的 sizeCompare
函数未返回任何内容。您需要实现的是 returns -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);
在比较函数中,您需要通过首先转换为
struct dirent **
来取消引用指针,就像这样const struct dirent *first_dirent = *(const struct dirent **) first_parameter;
这是因为传递的是每个元素的地址,而元素是指针,所以传递给函数的指针是指向指针的指针。他们的
void *
地址是一样的,但是不能直接把const struct dirent **
转成const struct dirent *
.你还有一个重要的问题,
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);
不是你想的那样,也不是你想的那样。
没有正确的大小,也许您应该先计算条目数并预测代码中第一个
malloc()
的值。或使用realloc()
并动态计算条目并同时分配指针。
还有:
正如@user3629249 in
所指出的那样,您的代码泄漏了内存
你不需要cast the return value from
malloc()
尽量不要将代码与声明混在一起,这样很难跟踪变量及其作用域。
您为 5 个
struct dirent *
指针分配了 space,但您从不检查计数变量是否达到或超过该值。这可能会导致未定义的行为。您的代码也会泄漏内存,因为您从不调用
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
的值限制为你分配的最大指针数space对于.