0

我正在尝试从文件中读取/反序列化元素列表(然后过滤掉其中的一些)。为此目的使用迭代器是一种有用的方法吗?

我目前的尝试是

#include <boost/iterator/iterator_adaptor.hpp>
class ReadIterator : public boost::iterator_adaptor<ReadIterator, Elem *, boost::single_pass_traversal_tag>
{
public:
    explicit ReadIterator(const char *filename) : reader(filename)  {}

private:
    friend class boost::iterator_core_access;

    void increment() {
         this->base_reference() = reader.readNext();
    }

    Reader reader;
};

这没有正确地释放内存(例如,readNew 返回一个指向新 Elem 的指针),这样做的正确方法是什么?另外,如何实际使用这样的迭代器,如何确定结果?还是有比使用迭代器更好的方法?

4

3 回答 3

4

简单的方法是使用 std::istream_iterator

std::vector<YourObjectClass>    data;

std::remove_copy_if(std::istream_iterator<YourObjectClass>(file),
                    std::istream_iterator<YourObjectClass>(),
                    std::back_inserter(data),
                    YourFilter
                   );

标准算法从输入中复制对象(类型为 YourObjectClass),如果过滤器函子返回 true,则将file它们放入向量中。data

唯一的条件是:

  • YourObjectClass 必须有一个输入流操作符
  • YourFilter 必须为 YourObjectClass 的对象重载 operator() 或者是一个接受 YourObjectClass 类型参数的函数。

简单的工作示例:

  • 我的对象是一条线。
  • 过滤掉以字母“A”开头的行

示例:

#include <vector>
#include <string>
#include <fstream>
#include <iterator>
#include <algorithm>

struct Line
{
    std::string   data;
};
std::istream& operator>>(std::istream& stream, Line& line)
{
    return std::getline(stream, line.data);
}
struct AFilter
{
    bool operator()(Line const& line) const
    {
        return line.data.size() > 0 && line.data[0] == 'A';
    }
};

int main()
{
    std::ifstream       file("Plop");
    std::vector<Line>   data;

    std::remove_copy_if(std::istream_iterator<Line>(file),
                        std::istream_iterator<Line>(),
                        std::back_inserter(data),
                        AFilter()
                       );
}
于 2011-04-19T05:44:47.233 回答
1

除了readNext()返回指向元素的原始指针之外,您是否可以构造调用,以便它返回一个引用计数的智能指针,当指针的引用计数变为零时,它将自动释放它的资源?要么,要么你将不得不找到一种方法来取回指针,这样你就可以在通过下一次调用when再次delete调用分配更多内存之前调用它。readNext()increment()

至于“结束”,在这种情况下你可以做的是在你的Reader类中进行一些测试,以检测你是否已经到达文件末尾或其他一些结束场景。如果有,则返回 false,否则返回 true。例如:

bool increment()
{
    if (reader.not_end_of_file())
    {
        this->base_reference() = reader.readNext();
        return true;
    }

    return false;
}

所以现在你可以调用increment()某种类型的循环,并且你会知道你何时到达文件结尾或其他结尾,因为该函数将返回 false。

于 2011-04-19T05:06:23.777 回答
1

为此目的使用迭代器很好。不过,您没有给出任何迹象表明现有的istream_iterator不适用于您的目的。至少在大多数情况下,您可以只operator>>为单个元素编写一个,并使用std::istream_iterator它从文件中读取这些元素的列表。

于 2011-04-19T05:26:33.493 回答