gpt4 book ai didi

c++ - 关于使用 C++ istream_iterator 从文件中读取部分数据的内容

转载 作者:搜寻专家 更新时间:2023-10-31 01:16:09 30 4
gpt4 key购买 nike

目标:有一个文本文件(在 HDD 上)包含用某种分隔符分隔的整数。

例子:

5245
234224
6534
1234

我需要将它们读入 STL 容器。

int main(int argc, char * argv[]) {
using namespace std;

// 1. prepare the file stream
string fileName;
if (argc > 1)
fileName = argv[1];
else {
cout << "Provide the filename to read from: ";
cin >> fileName;
}
unique_ptr<ifstream, ifstream_deleter<ifstream>> ptrToStream(new ifstream(fileName, ios::out));
if (!ptrToStream->good()) {
cerr << "Error opening file " << fileName << endl;
return -1;
}

// 2. value by value reading will be too slow on large data so buffer data
typedef unsigned int values_type;
const int BUFFER_SIZE(4); // 4 is for testing purposes. 16MB or larger in real life
vector<values_type> numbersBuffer(BUFFER_SIZE);
numbersBuffer.insert(numbersBuffer.begin(), istream_iterator<values_type>(*ptrToStream), istream_iterator<values_type>());
// ...

此代码的主要缺点是当文件非常大时我如何处理这个问题,所以我无法将所有内容存储在内存中?我也不想使用 push_back,因为它与间隔 insert 相比效率不高。


因此,问题是:如何使用 STL 有效地从文件中读取不超过 BUFFER_SIZE 个元素?

最佳答案

限制从输入迭代器读取的方法是创建一个包装器,该包装器计算到目前为止处理的元素数量以及其结束迭代器与该数字进行比较。一般地执行此操作并非易事,专门针对 std::istream_iterator<T> 执行此操作应该不会太难。也就是说,我认为最简单的方法是:

std::vector<T> buffer;
buffer.reserve(size);
std::istreambuf_iterator<T> it(in), end;
for (std::vector<T>::size_type count(0), capacity(size);
it != end && count != capacity; ++it, ++count) {
buffer.push_back(*it);
}

我知道你不想push_back()因为据说它很慢。但是,与 I/O 操作相比,我怀疑您是否能够衡量小的开销,尤其是对于 I/O 库的典型实现。

只是用一个包装迭代器的例子来圆满结束:下面是一个如何为 std::istream_iterator<T> 计数包装器的例子。可能看起来像。有许多不同的方法可以做到这一点,这只是其中一种。

#include <iostream>
#include <iterator>
#include <vector>
#include <sstream>

template <typename T>
class counted_istream_iterator:
public std::iterator<std::input_iterator_tag, T, std::ptrdiff_t>
{
public:
explicit counted_istream_iterator(std::istream& in): count_(), it_(in) {}
explicit counted_istream_iterator(size_t count): count_(count), it_() {}

T const& operator*() { return *this->it_; }
T const* operator->() { return it_->it_.operator->(); }
counted_istream_iterator& operator++() {
++this->count_; ++this->it_; return *this;
}
counted_istream_iterator operator++(int) {
counted_istream_iterator rc(*this); ++*this; return rc;
}

bool operator== (counted_istream_iterator const& other) const {
return this->count_ == other.count_ || this->it_ == other.it_;
}
bool operator!= (counted_istream_iterator const& other) const {
return !(*this == other);
}
private:
std::ptrdiff_t count_;
std::istream_iterator<T> it_;
};

void read(int count)
{
std::istringstream in("0 1 2 3 4 5 6 7 8 9");
std::vector<int> vec;
vec.insert(vec.end(), counted_istream_iterator<int>(in),
counted_istream_iterator<int>(count));
std::cout << "size=" << vec.size() << "\n";
}

int main()
{
read(4);
read(100);
}

关于c++ - 关于使用 C++ istream_iterator 从文件中读取部分数据的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9335723/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com