使用 C++迭代器从文件中读取列表?

发布于 2024-11-02 08:05:30 字数 610 浏览 1 评论 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 的指针),正确的方法是什么?另外,如何实际使用这样的迭代器,如何确定结束?或者有比使用迭代器更好的方法吗?

I am trying to read/deserialize a list of elements from a file (and then filter out some of them). It is a useful approach to use an iterator for this purpose?

My current try is

#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;
};

This does not properly deallocate memory (e.g., readNew returns a pointer to a new Elem), what is the right way to do this? Also, how would one actually use such an iterator, how can the end be determined? Or is there a better approach than using an iterator?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

败给现实 2024-11-09 08:05:30

执行此操作的简单方法是使用 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。

唯一的条件是:

  • YourObjectClass 必须有一个输入流运算符
  • YourFilter 必须重载 YourObjectClass 对象的 operator() 或者是采用 YourObjectClass 类型参数的函数。

简单的工作示例:

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

Exmpale:

#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()
                       );
}

The easy way to do this is to use the 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
                   );

The standard algorithm copies objects (of type YourObjectClass) from the input file and places them into the vector data if the filter functor returns true.

The only conditions are:

  • YourObjectClass must have an input stream operator
  • YourFilter must overload the operator() for objects of YourObjectClass or be a function that takes a parameter of type YourObjectClass.

Simple Working Example:

  • My object is a line.
  • Filter out line(s) that start with the letter 'A'

Exmpale:

#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()
                       );
}
迷你仙 2024-11-09 08:05:30

您是否可以构造调用,以便它返回一个引用计数的智能指针,而不是返回指向元素的原始指针,当指针的引用计数达到时,该指针将自动释放其资源变为零?要么,要么你必须找到一种方法来取回指针,以便你可以在通过下一次调用 readNext()< 分配更多内存之前对其调用 delete /code> 当再次调用 increment() 时。

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

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

    return false;
}

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

Rather than readNext() returning a raw pointer to an element, can you construct the call so that it returns a reference-counted smart-pointer that will automatically release it's resources when the reference-count to the pointer goes to zero? Either that, or you're going to have to find a way to fetch the pointer back so you can call delete on it before you allocate more memory via the next call to readNext() when increment() is called again.

As for the "end", what you could do in this case is have some test in your Reader class that detects if you've reached the end of the file or some other ending scenario. If you have, then return false, otherwise return true. For example:

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

    return false;
}

So now you could call increment() in some type of loop, and you'll know when you've hit the end-of-file or some other ending because the function will return false.

月竹挽风 2024-11-09 08:05:30

使用迭代器来达到这个目的是可以的。不过,您没有任何迹象表明现有的 istream_iterator 无法满足您的目的。至少在大多数情况下,您只需为单个元素编写一个 operator>> ,然后使用 std::istream_iterator 从文件中读取这些元素的列表。

Using an iterator for the purpose is fine. You haven't given any indication that the existing istream_iterator won't work for your purpose though. At least in most cases, you can just write an operator>> for a single element, and use std::istream_iterator to read a list of those elements from the file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文