你错过了几件事。首先不要使用幻数...2048 来自哪里? (舔手指,举起它说“是的,这应该够好了”?)limits.h 标头提供了宏PATH_MAX,它保证为所有文件系统条目提供足够的存储空间——改用它,例如:
#include <limits.h> /* for PATH_MAX */
...
char returnData[PATH_MAX] = ""; /* initialize to all zero is good habit */
(接下来,我确定是一个错字,但null 不是NULL)
如果您只是想将de->d_name 复制到returnData,则使用将de->d_name 复制到returnData 的函数,例如strcpy,例如
while ((de = readdir(dr)) != NULL) {
strcpy (returnData, de->d_name);
puts (returnData);
}
(当然,它在每次迭代时都会被覆盖,因此您不会使用returnData 返回文件列表,尽管returnData 是在当前函数中使用automatic-storage 声明的 如果在另一个函数中声明,则无法返回以开头...)
因此,将de->d_name 复制到returnData 的所有这些拐弯抹角的做法让您完全离开了起点,只能一次输出一个条目的名称。
实际为每个目录条目分配存储空间
我怀疑您真正想要做的是将目录中的所有文件读入存储,您可以从函数中返回名称列表,以便在代码中进行进一步处理。这是常见的做法,但不能用单个字符数组来做。
相反,您需要声明一个 pointer-to-pointer-to-char(例如“双指针”,char **dlist;),这将允许您分配一些初始数量的指针(比如8)然后realloc 更多指针,以容纳任何目录中的所有文件或目录名称。然后,您只分配每个名称所需的存储空间(nul-terminating 字符为 +1),并将每个名称的存储空间分配给其相应的指针,并将名称复制到您分配的新存储空间。
这样你就可以从任何你喜欢的地方返回一个指向你的名字集合的指针。 (记住对象将 allocated-storage 类型的生命周期一直持续到内存被释放或程序结束)类似:
#define NPTRS 8 /* initial number of pointers to allocate */
...
char **dlist = NULL, /* ptr-to-ptr-to-char for names */
size_t idx = 0, /* current index */
nptrs = NPTRS; /* number of pointers allocated */
...
/* allocate/validate nptrs pointers */
if ((dlist = calloc (nptrs, sizeof *dlist)) == NULL) {
perror ("calloc-nptrs");
return EXIT_FAILURE;
}
while ((de = readdir (dp))) {
...
/* check if dlist pointer limit reached - realloc */
if (idx == nptrs) { /* alwasy realloc to temporary pointer */
void *tmp = realloc (dlist, nptrs * 2 * sizeof *dlist);
if (!tmp) { /* validate reallocation */
perror ("realloc-dlist");
break; /* break, don't exit, original storage still valid */
}
dlist = tmp; /* assign reallocated block to dlist */
/* (optional) set all newly allocated memory to zero */
memset (dlist + nptrs, 0, nptrs * sizeof *dlist);
nptrs *= 2; /* update the number of allocated pointers */
}
/* allocate storage for name in dlist */
if ((dlist[idx] = malloc (strlen (de->d_name) + 1)) == NULL) {
char errbuf[PATH_MAX] = ""; /* storage for perror message */
sprintf (errbuf, "malloc failed '%s'", de->d_name);
perror (errbuf);
break;
}
strcpy (dlist[idx++], de->d_name); /* copy to new storage at idx */
}
现在您已将所有名称存储在dlist 中,其中idx 表示存储的名称数量。您可以从任何函数返回dlist(您还希望通过参数返回idx,以便存储的文件数也可以在调用函数中返回,或者将重新分配移动到您的副本下方(并包括'可选'memset) 以确保在最后一个有效条目之后始终有一个标记NULL 指针——这提供了另一种指示返回的有效名称的方法。
正如您已经(或将要)发现的那样,readdir 不会以任何特定顺序读取目录条目。为了对输出有用,使用qsort 排序是对您存储的文件名进行排序的最简单方法。下面的示例显示了一个简单的升序排序。
总而言之,您可以读取任何目录中的条目(默认情况下作为第一个参数传递给程序或来自'.'(当前目录))。代码将根据需要分配指针并重新分配。该代码为每个条目准确分配strlen(de->d_name) + 1 存储字符,将新的内存块分配给dlist[idx],然后将条目复制到dlist[idx](如果您的库,您可以使用dlist[idx] = strdup (de->d_name); 一步来分配和复制提供strdup -- 但请记住strdup 正在分配内存,因此您应该在继续之前验证成功。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> /* opendir */
#include <dirent.h> /* opendir, readdir */
#include <limits.h> /* for PATH_MAX */
#define NPTRS 8 /* initial number of pointers to allocate */
/** qsort string comparison (sort ascending) */
int cmpstr (const void *a, const void *b)
{
return strcmp (*(char * const *) a, *(char * const *) b);
}
int main (int argc, char **argv) {
char **dlist = NULL, /* ptr-to-ptr-to-char for names */
*dname = argc > 1 ? argv[1] : "."; /* dirname supplied (. default) */
size_t idx = 0, /* current index */
nptrs = NPTRS; /* number of pointers allocated */
struct dirent *de = NULL; /* dirent pointer (readdir) */
DIR *dp = opendir (dname); /* directory pointer (opendir) */
if (!dp) { /* validate directory open for reading */
char errbuf[PATH_MAX] = ""; /* storage for perror message */
sprintf (errbuf, "opendir failed on '%s'", dname);
perror (errbuf);
return EXIT_FAILURE;
}
/* allocate/validate nptrs pointers */
if ((dlist = calloc (nptrs, sizeof *dlist)) == NULL) {
perror ("calloc-nptrs");
return EXIT_FAILURE;
}
while ((de = readdir (dp))) {
/* skip dot files */
if (!strcmp (de->d_name, ".") || !strcmp (de->d_name, ".."))
continue;
/* check if dlist pointer limit reached - realloc */
if (idx == nptrs) { /* alwasy realloc to temporary pointer */
void *tmp = realloc (dlist, nptrs * 2 * sizeof *dlist);
if (!tmp) { /* validate reallocation */
perror ("realloc-dlist");
break; /* break, don't exit, original storage still valid */
}
dlist = tmp; /* assign reallocated block to dlist */
/* (optional) set all newly allocated memory to zero */
memset (dlist + nptrs, 0, nptrs * sizeof *dlist);
nptrs *= 2; /* update the number of allocated pointers */
}
/* allocate storage for name in dlist */
if ((dlist[idx] = malloc (strlen (de->d_name) + 1)) == NULL) {
char errbuf[PATH_MAX] = ""; /* storage for perror message */
sprintf (errbuf, "malloc failed '%s'", de->d_name);
perror (errbuf);
break;
}
strcpy (dlist[idx++], de->d_name); /* copy to new storage at idx */
}
closedir (dp); /* close directory */
/* qsort names stored in dlist */
qsort (dlist, idx, sizeof *dlist, cmpstr);
/* output all file/directory names stored, freeing memory as you go */
printf ("'%s' contains '%zu' files:\n\n", dname, idx);
for (size_t i = 0; i < idx; i++) {
puts (dlist[i]); /* output name */
free (dlist[i]); /* free storage for name */
}
free (dlist); /* free pointers */
return 0;
}
使用/输出示例
$ ./bin/opendir_readdir_dyn_char_basic .
'.' contains '1860' files:
3darrayaddr.c
3darrayalloc.c
3darrayfill.c
BoggleData.txt
DoubleLinkedList-old.c
DoubleLinkedList.c
DoubleLinkedList.diff
InputFile.txt
MonoSound.wav
...
xsplit.sh
xstrncpy.c
zeronotzero.c
内存使用/错误检查
另请注意,在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您都有 2 个职责:(1) 始终保留指向起始地址的指针 对于内存块,(2) 当不再需要它时可以释放。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化的值进行条件跳转,最后,以确认您释放了已分配的所有内存。
对于 Linux,valgrind 是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
$ valgrind ./bin/opendir_readdir_dyn_char_basic .
==16528== Memcheck, a memory error detector
==16528== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==16528== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==16528== Command: ./bin/opendir_readdir_dyn_char_basic .
==16528==
'.' contains '1860' files:
3darrayaddr.c
3darrayalloc.c
3darrayfill.c
BoggleData.txt
DoubleLinkedList-old.c
DoubleLinkedList.c
DoubleLinkedList.diff
InputFile.txt
MonoSound.wav
...
xsplit.sh
xstrncpy.c
zeronotzero.c
==16528==
==16528== HEAP SUMMARY:
==16528== in use at exit: 0 bytes in 0 blocks
==16528== total heap usage: 1,872 allocs, 1,872 frees, 109,843 bytes allocated
==16528==
==16528== All heap blocks were freed -- no leaks are possible
==16528==
==16528== For counts of detected and suppressed errors, rerun with: -v
==16528== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放已分配的所有内存并且没有内存错误。
查看一下,如果您还有其他问题,请告诉我。