C - 将文件夹和子文件夹中的所有 wav 文件路径放入具有递归函数的字符串数组中

C - Putting all the wav file paths from a folder and subfolder into an array of string with a recursive function

我在使用下面的代码时遇到了一些问题,它应该将文件夹的路径作为输入(在我的例子中 "pack"),并将路径放入它可以在文件夹中找到的每个 .wav 文件或在子文件夹中放入字符串数组。

您在下面看到的代码崩溃了。

在向你们寻求帮助之前,我自己进行了搜索,当尝试为该文件夹的第一个文件重新分配时,崩溃似乎附加在第二个子文件夹中

我正在测试的文件夹结构是这样的:

pack
├── _subfolder1
|   ├── wavefile1.wav
|   ├── wavefile2.wav
|   └── wavefile3.wav
├── _subfolder2
|   └── wavefile4.wav
├── _subfolder3
|   ├── wavefile5.wav
|   └── wavefile6.wav

代码:

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>

void find_dir_content(char* path, char** filepathlist, int* size)
{

    DIR* d = opendir(path);
    if(d == NULL)
        return;
    struct dirent* dir;

    while((dir = readdir(d)) != NULL) 
    {
        int isdir = 0;
        DIR* tmp;
        char f_path[255]; 
        sprintf(f_path, "%s/%s", path, dir->d_name);
        if((tmp = opendir(f_path))) { 
            closedir(tmp);
            isdir = 1;
        }

        if(!isdir) {

            char *dot = strrchr(dir->d_name, '.');
            if (dot && !strcmp(dot, ".wav")){
                char** tmp = realloc(filepathlist, sizeof(char*) * ((*size)  + 1));
                if (tmp == NULL)
                {
                    return;
                }
                else
                {
                    filepathlist = tmp;
                }
                char d_path[256];
                sprintf(d_path, "%s/%s", path, dir->d_name);
                filepathlist[*size] = d_path;
                //printf("%d : %s\n", *size, filepathlist[*size]);
                (*size)++;

            }
        }
        else if(isdir && strcmp(dir->d_name, ".") != 0 &&
            strcmp(dir->d_name, "..") != 0)
        {
            char d_path[256];
            sprintf(d_path, "%s/%s", path, dir->d_name);
            //printf("%s\n", d_path);
            find_dir_content(d_path, filepathlist, size);


        }
    }
    closedir(d);

}

int main(int argc, char** argv)
{
    int sizefilepathlist = 0;
    char** filepathlist = (char**) malloc(0*sizeof(char*));
    find_dir_content("pack", filepathlist, &sizefilepathlist);
    for(int i = 0; i< sizefilepathlist; i++){
        printf("%s", filepathlist[i]);
    }

    return 0;
}

编辑:我在 windows,我将 codelite 与 minGW(gcc) 一起使用,没有错误消息,windows 只是给我旧的 "has stopped working" 错误。

正如@unwind 在评论中指出的那样:

You're storing the address of a local variable. That will get you undefined behavior. You must dynamically allocate room for the path itself, not just the pointer to it.

最小的变化是更改行:

            filepathlist[*size] = d_path;

            filepathlist[*size] = strdup(d_path); // d_path will go out of scope - copy the string to dynamically allocated memory.

确保 #include <string.h> 获得 strdup 的原型。

编辑:

另一个问题是,当您 realloc(filepathlist) 时, main 中的变量仍然指向旧位置。这可以通过让 find_dir_content return 当前位置 filepathlist:

来解决
char **filepathlist(...) {
    ...
    return filepathlist;
}

主要是:

filepathlist = find_dir_content("pack", filepathlist, &sizefilepathlist);