Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.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++ 现代C++;围绕C Dirent.h的包装_C++_Pointers_C++11 - Fatal编程技术网

C++ 现代C++;围绕C Dirent.h的包装

C++ 现代C++;围绕C Dirent.h的包装,c++,pointers,c++11,C++,Pointers,C++11,我试图围绕C标题写一个现代C++包装,dio.H. 要在C中读取目录的内容,需要编写如下内容: int listdir(const char *path) { struct dirent *entry; DIR *dp; dp = opendir(path); if (dp == NULL) { perror("opendir"); return -1; } while((entry = readdir(dp))) puts(entry->

我试图围绕C标题写一个现代C++包装,dio.H. 要在C中读取目录的内容,需要编写如下内容:

int listdir(const char *path) {
  struct dirent *entry;
  DIR *dp;

  dp = opendir(path);
  if (dp == NULL) {
    perror("opendir");
    return -1;
  }

  while((entry = readdir(dp)))
    puts(entry->d_name);

  closedir(dp);
  return 0;
}
将此转换为现代C++,我有如下(其中Mydir和MydiRoad是/Cult>,MyFrase<<代码> STD::vector < /COD>)

这只起了一半作用。当我写它的时候,我没有意识到我只是在检查表达式
*m_dirent=*readdir(&*m_dir)
的地址是否存在(当然它确实存在!)。 根据,如果readdir(DIR*)已读取最后一个文件,并且没有更多的文件要读取,则返回空指针。但是,我不确定如何在不调用
m\u dirent
上的
.reset()
的情况下将dirent指针设置为dir指针正在读取的内容。但是,这样做只会导致读取垃圾数据,因为我假设当
dirent
被销毁时,文件指针会丢失

我如何转换这个

  while((entry = readdir(dp)))
    puts(entry->d_name);

<现代C++ >?p> 逗号运算符来营救

while(entry.reset(readdir(m_dir.get())), entry)
    puts(entry->d_name);

虽然,正如评论所说,对于文件系统来说,这不是一个奇妙的API。例如,透明地适应底层目录的迭代器会很酷。

我不确定这个计数是否像我在上个千年的UseNet中发布的那样现代(是一个改进版)。它稍微进化,成为1998年用于播种的首批成分之一。多亏了其他人的努力,它在Boost得到了进一步发展,并最终成为了一个新的平台,它构成了

然而,这一切都是从一个简单的想法开始的:如何很好地公开
opendir()
readdir()
,以及
closedir()
?有点明显的答案是:使用迭代器!以下是一个简单的版本和演示:

#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
#include <stdexcept>
#include <memory>
#include <dirent.h>

class dir_it
    : public std::iterator<std::input_iterator_tag, std::string>
{
    std::shared_ptr<DIR> dir;
    std::string          current;
    void advance() {
        dirent  entry;
        dirent* result;
        if (!readdir_r(dir.get(), &entry, &result) && result) {
            this->current = result->d_name;
        }
        else {
            this->dir.reset();
        }
    }
public:
    dir_it(std::string const& path)
        : dir(opendir(path.c_str()), [](DIR* dir){ dir && closedir(dir); }) {
        if (!dir) {
            throw std::runtime_error("failed to open directory '" + path + "'");
        }
        this->advance();
    }
    dir_it(): dir() {}

    std::string const& operator*() const { return this->current; }
    dir_it&            operator++() { this->advance(); return *this; }
    dir_it             operator++(int) {
        dir_it rc(*this);
        this->operator++();
        return rc;
    }
    bool operator==(dir_it const& other) const {
        return bool(this->dir) == bool(other.dir);
    }
    bool operator!=(dir_it const& other) const {
        return !(*this == other);
    }
};

int main() {
    std::copy(dir_it("."), dir_it(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类dir_it
:public std::迭代器
{
std::共享目录;
串电流;
作废预付款(){
直接进入;
直接结果;
if(!readdir_r(dir.get(),&entry,&result)&&result){
此->当前=结果->数据单元名称;
}
否则{
此->目录重置();
}
}
公众:
dir_it(标准::字符串常量和路径)
:dir(opendir(path.c_str()),[](dir*dir){dir&&closedir(dir);}){
如果(!dir){
抛出std::runtime_错误(“未能打开目录“”+path+”);
}
这个->前进();
}
dir_it():dir(){}
std::字符串常量和运算符*()常量{返回此->当前;}
dir_it&operator++(){this->advance();return*this;}
dir_it运算符++(int){
dir_it rc(*本);
这个->操作符++();
返回rc;
}
布尔运算符==(dir_it const和其他)const{
返回bool(this->dir)==bool(other.dir);
}
布尔运算符!=(dir_it const和其他)const{
返回!(*此==其他);
}
};
int main(){
std::copy(dir_it(“.”),dir_it(),std::ostream_迭代器(std::cout,“\n”);
}

当然,Boost和文件系统TS中的文件系统库比这个有点幼稚的实现功能更强。如果您的实现附带了TS的实现,我会使用它。如果C++不需要考虑Boost的实现。一般来说,下面的问题是你试图逐行逐行地从C到C++进行转换。这不是将非OO、<代码> C/<代码> API转化为C++接口的最佳方法。您必须查看整体设计,并对其应用适当的模式。例如,看看
boost
是如何实现文件系统API的。看看boost.filesystem(),它已被技术报告2接受。如果您可以访问Koenig的,他在他的一章中有一个例子。然而,这可能不算是现代C++,因为它早于标准一年左右,所以它没有任何经验,因为它建立。@ JoaNahan-Leffffel:我不知道凯尼格有一些目录上的东西。你还记得它是怎么暴露出来的吗?特别是,Koenig是否将目录公开为迭代器?@DietmarKühl:我需要再次查看代码。IIRC曾讨论过如何使其成为一个迭代器,但实际上并没有这样做的代码。
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
#include <stdexcept>
#include <memory>
#include <dirent.h>

class dir_it
    : public std::iterator<std::input_iterator_tag, std::string>
{
    std::shared_ptr<DIR> dir;
    std::string          current;
    void advance() {
        dirent  entry;
        dirent* result;
        if (!readdir_r(dir.get(), &entry, &result) && result) {
            this->current = result->d_name;
        }
        else {
            this->dir.reset();
        }
    }
public:
    dir_it(std::string const& path)
        : dir(opendir(path.c_str()), [](DIR* dir){ dir && closedir(dir); }) {
        if (!dir) {
            throw std::runtime_error("failed to open directory '" + path + "'");
        }
        this->advance();
    }
    dir_it(): dir() {}

    std::string const& operator*() const { return this->current; }
    dir_it&            operator++() { this->advance(); return *this; }
    dir_it             operator++(int) {
        dir_it rc(*this);
        this->operator++();
        return rc;
    }
    bool operator==(dir_it const& other) const {
        return bool(this->dir) == bool(other.dir);
    }
    bool operator!=(dir_it const& other) const {
        return !(*this == other);
    }
};

int main() {
    std::copy(dir_it("."), dir_it(), std::ostream_iterator<std::string>(std::cout, "\n"));
}