如何迭代到较小的容器(即步幅!= 1)

发布于 2024-10-26 11:44:49 字数 1305 浏览 8 评论 0原文

此处有一个在精神上非常相似的问题。不幸的是,这个问题没有引起太多回应 - 我想我会问一个更具体的问题,希望可以建议替代方法。

我正在将二进制文件写入 std::cin (使用 tar --to-command=./myprog)。 二进制文件恰好是一组浮点数,我想将数据放入 std::vector - 最好是 C++ 方式。

我可以很好地生成 std::vector (感谢 这个答案

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

int
main  (int ac, char **av)
{
  std::istream& input = std::cin;
  std::vector<char> buffer;
  std::copy( 
        std::istreambuf_iterator<char>(input), 
           std::istreambuf_iterator<char>( ),
           std::back_inserter(buffer)); // copies all data into buffer
}

我现在想将我的 std::vector 转换为 std::vector ,大概是用 std::transform 和一个执行转换的函数(例如,从 char[2]float)。然而,我很挣扎,因为我的 std::vector 的元素数量是 std::vector 的一半。如果我能以 2 的步幅进行迭代,那么我想我会很好,但从上一个问题来看,我似乎无法做到这一点(至少不能优雅地做到)。

There is a question that is very similar in spirit here. Unfortunately that question didn't prompt much response - I thought I would ask a more specific question with the hope that an alternative method can be suggested.

I'm writing a binary file into std::cin (with tar --to-command=./myprog).
The binary file happens to be a set of floats and I want to put the data into std::vector<float> - ideally the c++ way.

I can generate a std::vector<char> very nicely (thanks to this answer)

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

int
main  (int ac, char **av)
{
  std::istream& input = std::cin;
  std::vector<char> buffer;
  std::copy( 
        std::istreambuf_iterator<char>(input), 
           std::istreambuf_iterator<char>( ),
           std::back_inserter(buffer)); // copies all data into buffer
}

I now want to transform my std::vector<char> into a std::vector<float>, presumably with std::transform and a function that does the conversion (a char[2] to a float, say). I am struggling however, because my std::vector<float> will have half as many elements as std::vector<char>. If I could iterate with a stride of 2 then I think I would be fine, but from the previous question it seems that I cannot do that (at least not elegantly).

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

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

发布评论

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

评论(3

你又不是我 2024-11-02 11:44:49

我会编写自己的类来读取两个字符并将其转换为浮点数。

struct FloatConverter
{
    // When the FloatConverter object is assigned to a float value
    // i.e. When put into the vector<float> this method will be called
    //      to convert the object into a float.
    operator float() { return 1.0; /* How you convert the 2 chars */ }

    friend std::istream& operator>>(std::istream& st, FloatConverter& fc)
    {
        // You were not exactly clear on what should be read in.
        // So I went pedantic and made sure we just read 2 characters.
        fc.data[0] = str.get();
        fc.data[1] = str.get();
        retun str;
    }
    char   data[2];
 };

根据 GMan 的评论:

struct FloatConverterFromBinary
{
    // When the FloatConverterFromBinary object is assigned to a float value
    // i.e. When put into the vector<float> this method will be called
    //      to convert the object into a float.
    operator float() { return data }

    friend std::istream& operator>>(std::istream& st, FloatConverterFromBinary& fc)
    {
        // Use reinterpret_cast to emphasis how dangerous and unportable this is.
        str.read(reinterpret_cast<char*>(&fc.data), sizeof(float));
        retun str;
    }

    float  data;
};

然后像这样使用它:

int main  (int ac, char **av)
{
  std::istream& input = std::cin;
  std::vector<float> buffer;

  // Note: Because the FloatConverter does not drop whitespace while reading
  //       You can potentially use std::istream_iterator<>
  //
  std::copy( 
           std::istreambuf_iterator<FloatConverter>(input), 
           std::istreambuf_iterator<FloatConverter>( ),
           std::back_inserter(buffer));
}

I would write my own class that reads two chars and converts it to float.

struct FloatConverter
{
    // When the FloatConverter object is assigned to a float value
    // i.e. When put into the vector<float> this method will be called
    //      to convert the object into a float.
    operator float() { return 1.0; /* How you convert the 2 chars */ }

    friend std::istream& operator>>(std::istream& st, FloatConverter& fc)
    {
        // You were not exactly clear on what should be read in.
        // So I went pedantic and made sure we just read 2 characters.
        fc.data[0] = str.get();
        fc.data[1] = str.get();
        retun str;
    }
    char   data[2];
 };

Based on comments by GMan:

struct FloatConverterFromBinary
{
    // When the FloatConverterFromBinary object is assigned to a float value
    // i.e. When put into the vector<float> this method will be called
    //      to convert the object into a float.
    operator float() { return data }

    friend std::istream& operator>>(std::istream& st, FloatConverterFromBinary& fc)
    {
        // Use reinterpret_cast to emphasis how dangerous and unportable this is.
        str.read(reinterpret_cast<char*>(&fc.data), sizeof(float));
        retun str;
    }

    float  data;
};

Then use it like this:

int main  (int ac, char **av)
{
  std::istream& input = std::cin;
  std::vector<float> buffer;

  // Note: Because the FloatConverter does not drop whitespace while reading
  //       You can potentially use std::istream_iterator<>
  //
  std::copy( 
           std::istreambuf_iterator<FloatConverter>(input), 
           std::istreambuf_iterator<FloatConverter>( ),
           std::back_inserter(buffer));
}
将军与妓 2024-11-02 11:44:49

在我看来,最好的答案是编写一对您自己的迭代器,以您想要的方式解析文件。您可以将 std::vector 更改为 std::vector 并使用相同的 streambuf 迭代器(前提是输入已格式化)值之间至少有一个空格。

It seems to me that the best answer is to write a pair of your own iterators that parse the file the way that you want. You could change std::vector<char> to std::vector<float> and use the same streambuf iterators provided the input was formatted with at least one space between values.

策马西风 2024-11-02 11:44:49

使用boost范围适配器:

boost::copy(istream_range(input)|stride(2),back_inserter(buffer));

您可能需要编写自己的istreambuf_iterator,即微不足道

use boost range adaptors:

boost::copy(istream_range(input)|stride(2),back_inserter(buffer));

you might need to write your own istreambuf_iterator, which is trivial.

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