Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在linux上运行的opendir()在名称和空格上失败_C++_Linux_Directory_Io - Fatal编程技术网

C++ 在linux上运行的opendir()在名称和空格上失败

C++ 在linux上运行的opendir()在名称和空格上失败,c++,linux,directory,io,C++,Linux,Directory,Io,我的程序探索当前目录和所有子目录以打印所有文件名。但是,当目录名称中有空格时,它会产生分段错误。这只发生在linux-windows上,工作正常 名称存储在dirent.d_name中,它是字符[256]。我尝试过使用它,使用c_str()将其转换为c字符串,我尝试过将目录名编码为代码,我尝试过转义空间(尽管我认为我做得不正确) 如果将DIR*指针和struct dirent*指针作为参数传递,而不是简单地形成并传递下一个打开路径,则会遇到问题。您希望在递归函数本身中处理目录的打开,而不是作为从

我的程序探索当前目录和所有子目录以打印所有文件名。但是,当目录名称中有空格时,它会产生分段错误。这只发生在linux-windows上,工作正常

名称存储在
dirent.d_name
中,它是
字符[256]
。我尝试过使用它,使用
c_str()
将其转换为c字符串,我尝试过将目录名编码为代码,我尝试过转义空间(尽管我认为我做得不正确)


如果将
DIR*
指针和
struct dirent*
指针作为参数传递,而不是简单地形成并传递下一个打开路径,则会遇到问题。您希望在递归函数本身中处理目录的打开,而不是作为从
main()
传递的单个指针,例如

void print_dir_rec(const char *name)
{
    DIR *dir;
    struct dirent *entry;

    if (!(dir = opendir(name)))
        return;

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) {
            char path[1024];
            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
                continue;
            snprintf(path, sizeof(path), "%s/%s", name, entry->d_name);
            printf("[%s]\n", entry->d_name);
            print_dir_rec(path);
        }
    }
    closedir(dir);
}
注意:您可以根据需要或使用
path\u MAX
宏来调整为
path
提供的字符数)

这样,就不会有单个指针在每次递归调用中被重用,从而导致问题。列出当前目录下所有目录的简短示例可以是:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>

void print_dir_rec(const char *name)
{
    DIR *dir;
    struct dirent *entry;

    if (!(dir = opendir(name)))
        return;

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) {
            char path[1024];
            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
                continue;
            snprintf(path, sizeof(path), "%s/%s", name, entry->d_name);
            printf("[%s]\n", entry->d_name);
            print_dir_rec(path);
        }
    }
    closedir(dir);
}

int main(void) {
    print_dir_rec(".");
    return 0;
}
#包括
#包括
#包括
#包括
#包括
无效打印目录记录(常量字符*名称)
{
DIR*DIR;
结构方向*条目;
如果(!(dir=opendir(name)))
回来
while((entry=readdir(dir))!=NULL){
如果(条目->数据类型==DT\U目录){
字符路径[1024];
如果(strcmp(条目->数据单元名称,“.”)=0 | | strcmp(条目->数据单元名称,“…”)==0)
持续
snprintf(路径,sizeof(路径),%s/%s”,名称,条目->d_名称);
printf(“[%s]\n”,条目->数据单元名称);
打印目录记录(路径);
}
}
closedir(dir);
}
内部主(空){
打印目录记录(“.”);
返回0;
}
看看开场白和阅读是如何处理的,需要传递哪些信息。通过在每个递归调用中为
path
提供存储,您可以保证名称在递归调用返回之前保持在范围内


如果您还有其他问题,请告诉我。

dname
是属于
readdir
的存储(可能会被重新使用),您可以从中复制以将名称保存在其他存储中,但您不能对
dname
成员本身进行任何转换或操作,它只是被下一个名称覆盖。我的意思是,我尝试从dname构造一个字符串,然后传递string.c_str()而不是dname。通常,您希望存储在整个递归调用的范围内,例如
char path[1024]
,然后使用
snprintf
创建路径,例如,使用
name
中的当前目录,您可以使用
snprintf(路径,大小(路径),“%s/%s”,名称,条目->d_名称)
No让你的函数用一个
const char*
代替
DIR*DIR
,例如,
print\u DIR\u rec(const char*name)
并进行递归调用
print\u DIR\u rec(path)
。完成后你永远不会调用
closedir()
。如果你能使用C++17,这会变得非常简单。C++的旧版本也有BooS.FooScript版本,非常感谢它的完美工作!你能在snprintf()上展开一点吗?它到底是做什么的?为什么有必要?(对不起,我得去接孩子),
sprintf
在这种情况下允许您将格式化字符串写入缓冲区(
path
)。为了将新目录与当前路径相结合,必须在它们之间放置目录分隔符。这就是
sprintf
(或上面使用的
snprintf
)发挥作用的地方。格式字符串
“%s/%s”
允许您将
'/'
放置在两个字符串之间,将新的目录名添加到当前路径的末尾。在C++中,你可以用<代码> STD::String 来简单地连接字符串。(尽管具有自动存储持续时间的固定阵列效率更高)
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>

void print_dir_rec(const char *name)
{
    DIR *dir;
    struct dirent *entry;

    if (!(dir = opendir(name)))
        return;

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) {
            char path[1024];
            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
                continue;
            snprintf(path, sizeof(path), "%s/%s", name, entry->d_name);
            printf("[%s]\n", entry->d_name);
            print_dir_rec(path);
        }
    }
    closedir(dir);
}

int main(void) {
    print_dir_rec(".");
    return 0;
}