我在一个递归函数中声明了一个数组。是否可以在输出前对其进行排序?我从另一个递归函数获得的大小。
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);
}
答案 0 :(得分:1)
警告: require 'dompdf/autoload.inc.php';
$html = empty( $html ) ? $this->get_order_pdf_html( $order_id, 'pdf' ) : $html;
$dompdf = new Dompdf( array(
'isRemoteEnabled' => true,
) );
$dompdf->setPaper( 'A4', 'portrait' );
$dompdf->set_option('isHtml5ParserEnabled', true);
$dompdf->loadHtml( $html, 'UTF-8' );
$dompdf->render();
$output = $dompdf->output();
if( $save_pdf ) {
$invoice_file_name = sprintf( '%s/uploads/document-%s-%s.pdf', WP_CONTENT_DIR, $order_id, time("H:s") );
file_put_contents( $invoice_file_name, $output);
return $invoice_file_name;
}
if( $download_pdf ) {
$dompdf->stream( sprintf( "%s-%s", __('document'), $order_id ) );
return true;
}
return $output;
}
保存一个本地变量地址,并在每次循环时对其进行修改,因此所有名称都相同,您需要保存一个副本( strdup )
对于 listFilesRecursively 的每次调用,您在堆栈中使用了1000个以上的字节,最好不要在堆栈中使用该字符串,而直接使用堆中分配的路径
我不希望将文件和计数器作为局部变量,而将它们放出去
提案
files[counter].name=path
我只记住常规文件的路径名和大小,未保存目录和动态链接等
我按路径名排序
每次文件太小时,我都会添加NFILES,NFILES可以是任意数字> 0
在valgrind下执行:
#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;
}
答案 1 :(得分:0)
您的方法无效:
files
定义。path
的指针。使files
成为全局变量是可能的,但是应避免使用全局变量。相反,应在递归下降过程中找到更多条目时,向指针传递递归函数外部定义的结构,并在此结构内重新分配数组。每个文件的路径副本应使用strdup
分配。为了限制堆栈空间要求,path
也可以是此结构的一部分,并将目录部分的长度传递给递归函数。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
struct file {
char *name;
struct {
long st_size;
} file_info;
};
typedef struct dir_state {
char path[1024];
struct file *files;
int files_size;
int files_count;
} dir_state;
int listFilesRecursively(dir_state *sp) {
struct dirent *dp;
struct stat buf;
int counter = 0;
int path_len = strlen(sp->path);
DIR *dir = opendir(sp->path);
if (!dir)
return 0;
while ((dp = readdir(dir)) != NULL) {
if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0) {
snprintf(sp->path + path_len, sizeof(sp->path) - path_len, "/%s", dp->d_name);
if (sp->files_count == sp->files_size) {
int new_size = sp->files_size * 3 / 2 + 16;
struct file *new_p = realloc(sp->files, new_size * sizeof(*new_p));
if (new_p == NULL)
return -1;
sp->files_size = new_size;
sp->files = new_p;
}
memset(&sp->files[sp->files_count], 0, sizeof(struct file));
sp->files[sp->files_count].name = strdup(sp->path);
if (!stat(sp->path, &buf))
sp->files[sp->files_count].file_info.st_size = buf.st_size;
printf("%s%s%ld%s\n", sp->files[sp->files_count].name, " - ",
sp->files[sp->files_count].file_info.st_size, "bytes");
sp->files_count++;
counter++;
listFilesRecursively(sp);
}
}
closedir(dir);
sp->path[path_len] = '\0';
return counter;
}
int cmp_name(const void *a, const void *b) {
const struct file *aa = a;
const struct file *bb = b;
return strcmp(aa->name, bb->name);
}
int cmp_size_name(const void *a, const void *b) {
const struct file *aa = a;
const struct file *bb = b;
if (aa->file_info.st_size < bb->file_info.st_size)
return -1;
if (aa->file_info.st_size > bb->file_info.st_size)
return +1;
return strcmp(aa->name, bb->name);
}
int main(int argc, char *argv[]) {
dir_state ds = { "", NULL, 0, 0 };
int i;
if (argc < 2) {
strcpy(ds.path, ".");
listFilesRecursively(&ds);
} else {
for (i = 1; i < argc; i++) {
strcpy(ds.path, argv[i]);
listFilesRecursively(&ds);
}
}
printf("\nFiles sorted by name:\n");
qsort(ds.files, ds.files_count, sizeof(*ds.files), cmp_name);
for (i = 0; i < ds.files_count; i++) {
printf("%10ld %s\n", ds.files[i].file_info.st_size, ds.files[i].name);
}
printf("\nFiles sorted by size and name:\n");
qsort(ds.files, ds.files_count, sizeof(*ds.files), cmp_size_name);
for (i = 0; i < ds.files_count; i++) {
printf("%10ld %s\n", ds.files[i].file_info.st_size, ds.files[i].name);
}
for (i = 0; i < ds.files_count; i++) {
free(ds.files[i].name);
}
free(ds.files);
return 0;
}
注意:
snprintf
强制执行了路径长度限制,因此不会导致无限递归。