c - 我在递归函数中声明了一个数组。我该如何排序?
问题描述
我在递归函数中声明了一个数组。是否可以在输出之前对其进行排序?我从另一个递归函数得到的大小。
void listFilesRecursively(char *basePath, int size) {
char path[1000];
struct dirent *dp;
struct file files[size];
struct stat buf;
DIR *dir = opendir(basePath);
int counter = 0;
if (!dir) return;
while ((dp = readdir(dir)) != NULL) {
if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0) {
strcpy(path, basePath);
strcat(path, "/");
strcat(path, dp->d_name);
files[counter].name = path;
stat(path, &buf);
files[counter].file_info.st_size = buf.st_size;
printf("%s%s%ld%s\n", files[counter].name, " - ",
files[counter].file_info.st_size, "bytes");
counter++;
listFilesRecursively(path, size);
}
}
closedir(dir);
}
解决方案
警告:files[counter].name=path
保存一个局部变量地址,并在每个循环中修改它,因此所有名称都相同,您需要保存它的副本(strdup)
对于listFilesRecursively的每次调用,您在堆栈中使用超过 1000 个字节,最好不要在堆栈中使用该字符串并直接使用在堆中分配的路径
我没有看到将文件和计数器作为局部变量的兴趣,您将它们释放出去
提案
#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define NFILES 100;
typedef struct file {
char * name;
struct stat file_info;
} file;
void listFilesRecursively(char *basePath, file ** files, int * size, int * index)
{
DIR *dir = opendir(basePath);
if (!dir)
return;
struct dirent *dp;
struct stat buf;
while ((dp = readdir(dir)) != NULL)
{
if ((strcmp(dp->d_name, ".") != 0) && (strcmp(dp->d_name, "..") != 0))
{
size_t sz = strlen(basePath);
char * pathname = malloc(sz + strlen(dp->d_name) + 2);
if (pathname == NULL) {
/* out of memory */
closedir(dir);
return;
}
strcpy(pathname, basePath);
pathname[sz] = '/';
strcpy(pathname + sz + 1, dp->d_name);
stat(pathname, &buf);
if (S_ISDIR(buf.st_mode)) {
/* suppose dirs not memorized */
listFilesRecursively(pathname, files, size, index);
free(pathname);
}
else if (S_ISREG(buf.st_mode)) {
/* a file, memorize it */
if (++*index == *size) {
*size += NFILES;
*files = realloc(*files, (*size) * sizeof(file));
}
(*files)[*index].file_info = buf;
(*files)[*index].name = pathname;
}
else
/* bypassed */
free(pathname);
}
}
closedir(dir);
}
int compPathname(const void * a, const void * b)
{
return strcmp(((file *) a)->name, ((file *) b)->name);
}
int main()
{
int size = NFILES;
int index = -1;
file * files = malloc(size * sizeof(file));
listFilesRecursively(".", &files, &size, &index);
if (index != -1) {
qsort(files, index + 1, sizeof(file), compPathname);
/* write and free memory */
for (int i = 0; i <= index; ++i) {
printf("%s : %ld\n", files[i].name, (long) files[i].file_info.st_size);
free(files[i].name);
}
}
free(files);
return 0;
}
我只记住常规文件的路径名和大小,不保存目录和动态链接等
我按路径名排序
每次文件太小我都会添加 NFILES,NFILES 可以是任何数字 > 0
在 valgrind 下执行:
==9329== Memcheck, a memory error detector
==9329== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9329== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9329== Command: ./a.out
==9329==
./.X0-lock : 11
./a.out : 12920
./f.c : 2485
./vgdb-pipe-shared-mem-vgdb-9329-by-pi-on-??? : 36
==9329==
==9329== HEAP SUMMARY:
==9329== in use at exit: 0 bytes in 0 blocks
==9329== total heap usage: 35 allocs, 35 frees, 339,242 bytes allocated
==9329==
==9329== All heap blocks were freed -- no leaks are possible
==9329==
==9329== For counts of detected and suppressed errors, rerun with: -v
==9329== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
推荐阅读
- ios - iOS 和 android 平台上的应用程序安全性
- jquery - 更改根的 HTML 颜色选择器:css 变量
- python-3.x - paramiko stdout 的输出错误地传输行
- sql - 我如何计算咨询的人数
- extjs - 如何从 Web 浏览器 CORS 策略阻止的 Ajax 请求 (POST) 中的 Web 服务中检索数据
- go - 无法评估字段
在类型字符串中 - arrays - 我可以从保存在 UserDefaults 中的数据中填充数组吗?
- php - PHP将数组排序为两列
- reactjs - 如何在 react/redux 应用程序中向 axios.create 添加标头
- python-3.x - Beautifulsoup 过滤“find_all”结果,通过正则表达式限制为 .jpeg 文件