C++中Python生成器的等效缓冲读取

2024-10-01 09:27:37 发布

您现在位置:Python中文网/ 问答频道 /正文

Guido Van Rossum在article中演示了Python的简单性,并将此函数用于对未知长度的文件进行缓冲读取:

def intsfromfile(f):
    while True:
        a = array.array('i')
        a.fromstring(f.read(4000))
        if not a:
            break
        for x in a:
            yield x
因为速度的原因,我需要在C++中做同样的事情!我有许多文件包含无符号64位整数的排序列表,我需要合并它们。我找到了一个很好的code来合并向量。在

我被困在如何使一个未知长度的文件的ifstream呈现为一个向量,它可以被愉快地迭代到文件的末尾。有什么建议吗?我是否用一个istreambuf_迭代器查找正确的树?在


Tags: 文件函数truereadifdefarticlearray
1条回答
网友
1楼 · 发布于 2024-10-01 09:27:37

为了将ifstream(或者实际上是任何输入流)伪装成迭代器的形式,您需要使用istream_iteratoristreambuf_iterator模板类。前者对于需要关注格式的文件很有用。例如,可以将一个充满空格分隔整数的文件读入向量的迭代器范围构造函数,如下所示:

#include <fstream>
#include <vector>
#include <iterator> // needed for istream_iterator

using namespace std;

int main(int argc, char** argv)
{
    ifstream infile("my-file.txt");

    // It isn't customary to declare these as standalone variables,
    // but see below for why it's necessary when working with
    // initializing containers.
    istream_iterator<int> infile_begin(infile);
    istream_iterator<int> infile_end;

    vector<int> my_ints(infile_begin, infile_end);

    // You can also do stuff with the istream_iterator objects directly:
    // Careful! If you run this program as is, this won't work because we
    // used up the input stream already with the vector.

    int total = 0;
    while (infile_begin != infile_end) {
        total += *infile_begin;
        ++infile_begin;
    }

    return 0;
}

istreambuf_iterator用于一次读取一个字符的文件,而不考虑输入的格式。也就是说,它将返回所有字符,包括空格、换行符等。根据您的应用程序,这可能更合适。在

注意:scottmeyers在effectivestl中解释了为什么上面需要为istream_iterator单独声明变量。通常,你会这样做:

^{pr2}$ <>但是,C++实际上以难以置信的怪异方式解析第二行。它将其视为一个名为my_ints的函数的声明,该函数接受两个参数并返回一个vector<int>。第一个参数是istream_iterator<int>类型,名为infile(parathese被忽略)。第二个参数是一个没有名字的函数指针,它接受零参数(因为paratheses),并返回一个istream_iterator<int>类型的对象。在

很酷,但如果你不小心的话,也会让你很恼火。在


编辑

下面是一个使用istreambuf_iterator读取端到端排列的64位数字文件的示例:

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

using namespace std;

int main(int argc, char** argv)
{
    ifstream input("my-file.txt");
    istreambuf_iterator<char> input_begin(input);
    istreambuf_iterator<char> input_end;

    // Fill a char vector with input file's contents:
    vector<char> char_input(input_begin, input_end);
    input.close();

    // Convert it to an array of unsigned long with a cast:
    unsigned long* converted = reinterpret_cast<unsigned long*>(&char_input[0]);
    size_t num_long_elements = char_input.size() * sizeof(char) / sizeof(unsigned long);

    // Put that information into a vector:
    vector<unsigned long> long_input(converted, converted + num_long_elements);

    return 0;
}

现在,我个人更不喜欢这种解决方案(使用reinterpret_cast,公开char_input的数组),但是我对istreambuf_iterator不太熟悉,不能轻松地使用一个超过64位字符的模板,这会使这一点变得容易得多。在

相关问题 更多 >