我不想称它为包装器,但现在还没有想到其他名称,因此我将在剩下的问题中错误地使用它--它只是一个将C++函数添加到dirent.h中的类,但它非常适合我的用例。
所有的代码都工作得很好,但是我从未使用过dirent.h库,直接进入C++包装是件很重要的事情,所以我对它在实际场景中的性能和内存使用非常不安全。
但是,当然,也请判断可读性-我想知道我是否应该添加评论,或者我的命名方案和布局是否是不言自明的。
我正在开发基于C++的文件管理器,它需要返回整个目录的向量的函数,当然,它可以在一个循环中显示它。它还需要一些更多的信息(我猜是元数据),比如它的类型,这样它就可以完成所有花哨的颜色语法。
以下是目前为止的最终版本(带有一些调试代码):
#ifndef INODECLASS
#define INODECLASS
#include <dirent.h>
#include <string.h>
#include <iostream>
#include <vector>
#include <string>
class Inode
{
public:
struct InodeMeta {
std::string name;
std::string path;
unsigned char type;
};
private:
std::string pwd_path_;
std::vector<InodeMeta *> buffer_;
public:
Inode(const std::string &);
~Inode();
void ClearBuffer();
bool ReloadBuffer(const std::string &);
std::vector<InodeMeta> DumpBuffer(const std::string &);
};
#endif#include "inode.h"
Inode::Inode(const std::string &arg_path = ".") {
if ( !ReloadBuffer(arg_path) )
ClearBuffer();
}
Inode::~Inode() {
ClearBuffer();
}
void Inode::ClearBuffer() {
for (auto &item : buffer_)
delete item;
buffer_.clear();
}
bool Inode::ReloadBuffer(const std::string &arg_path = "") {
if (arg_path.length() != 0) pwd_path_ = arg_path;
DIR *dirstream;
dirent *diritem;
ClearBuffer();
if ( (dirstream = opendir(pwd_path_.c_str())) != NULL )
{
while ( (diritem = readdir(dirstream)) != NULL ) {
if ( strcmp(diritem->d_name, ".") != 0 &&
strcmp(diritem->d_name, "..") != 0 )
buffer_.emplace_back( new InodeMeta{ std::string(diritem->d_name),
std::string(pwd_path_) + "/" + std::string(diritem->d_name),
diritem->d_type} );
}
closedir(dirstream);
}
else return false;
return true;
}
std::vector<Inode::InodeMeta> Inode::DumpBuffer(const std::string &arg_path = "") {
if (arg_path.length() != 0) ReloadBuffer(arg_path);
std::vector<InodeMeta> ret_list;
for (auto &item : buffer_)
ret_list.push_back(*item);
return ret_list;
}
//DEBUG ONLY//
#include <iostream>
int main() {
Inode I;
std::vector<Inode::InodeMeta> inodelist = I.DumpBuffer();
for (auto &item : inodelist)
std::cout << item.name << " ; " << item.path << '\n';
I.ReloadBuffer("/tmp/");
inodelist.clear();
inodelist = I.DumpBuffer();
for (auto &item : inodelist)
std::cout << item.name << " ; " << item.path << '\n';
}以防万一你要么想看整个项目(我像3天前就开始了,别对我评价太严),要么做一个快速的git clone,自己测试一下这里。
发布于 2016-12-16 22:20:16
这是我最讨厌的事之一:
Inode(const std::string &);头文件/类定义的重点(至少在我的头脑中)是将代码的接口与代码的实现分开。不将参数名称放入函数声明中会导致接口不完整。当然,您知道参数是什么,但是您编写了代码。从读取您的类头,我不知道字符串可能表示什么,没有注释告诉我,没有名称,所以我要么依赖您的文档(?)或者必须看一下实现才能弄清楚。
默认参数只影响可以看到它们的代码。您已经为您的方法定义了默认参数,但只在实现文件中。我觉得有点奇怪。如果这是一个好的默认,它应该在标题中。
描述性命名非常重要,并且大大减少了新手对代码的学习时间。我得去看看Inode,看看是什么。如果您有这方面的经验,这可能是有意义的,但作为文件夹结构的实现,它不是我想要的名字。在我看来,pwd的意思是“打印工作目录”,所以pwd_path_似乎是个奇怪的名字。也许wd_path会更好。buffer_是非常难以描述的.这是一个元数据列表,为什么不称之为元数据呢?
您的方法命名也有类似的问题。DumpBuffer并没有真正说“读取目录并将元数据返回给我”。
你的一些空白行对我来说没有什么意义,它们会使你的代码更难读。考虑到这一点:
if ( strcmp(diritem->d_name, ".") != 0 &&
strcmp(diritem->d_name, "..") != 0 )
buffer_.emplace_back( new InodeMeta{ std::string(diritem->d_name),
std::string(pwd_path_) + "/" + std::string(diritem->d_name),
diritem->d_type} );您设置了一个未带大括号的if语句,然后在if和它所属的代码之间留出空行。这是被误解的邀请。对于函数末尾的其他条件,我也有同样的感觉:
}
else return false;关闭if,留下一个空行,然后将其放入。它使else感到分离。
您从在buffer_中存储指针而不是InodeMeta实例中得到了什么。既然您仍然从DumpBuffer方法返回副本,感觉就好像只是添加了额外的处理要求,而没有什么好处吗?如果您想保存复制,那么存储和返回一个shared_ptr可能会更有效。
我不确定让DumpBuffer是否有不同的行为取决于您是否传递空字符串是一个好主意。如果我传入"/someFolder“,那么文件夹就会被读取。如果我再次传入它,"/someFolder",则会再次读取该文件夹(例如,任何新文件都会被注意到)。如果第二个调用是我传入的"“,那么原始文件夹内容就会被返回。如果这是我想要的行为,那么我至少会在头/文档中添加一个注释,因为这不是我所期望的。
https://codereview.stackexchange.com/questions/150097
复制相似问题