как перебрать в меньший контейнер (т.е. шагать! = 1) - PullRequest
3 голосов
/ 24 марта 2011

Есть вопрос, который очень похож по духу здесь . К сожалению, этот вопрос не вызвал большого ответа - я подумал, что задам более конкретный вопрос в надежде, что можно будет предложить альтернативный метод.

Я записываю двоичный файл в std::cintar --to-command=./myprog). Бинарный файл представляет собой набор чисел с плавающей точкой, и я хочу поместить данные в std::vector<float> - в идеале - в способ C ++.

Я могу очень хорошо сгенерировать std::vector<char> (благодаря этот ответ )

#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<char> в std::vector<float>, предположительно с std::transform и функцией, которая выполняет преобразование (скажем, char[2] в float). Однако я борюсь, потому что в моем std::vector<float> будет вдвое меньше элементов, чем в std::vector<char>. Если бы я мог повторить шаг с шагом 2, то я думаю, что я был бы в порядке, но из предыдущего вопроса кажется, что я не могу этого сделать (по крайней мере, не элегантно).

Ответы [ 3 ]

5 голосов
/ 24 марта 2011

Я бы написал свой собственный класс, который читает два символа и конвертирует его в число с плавающей точкой.

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

Затем используйте его так:1007 *

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));
}
0 голосов
/ 10 июля 2014

используйте адаптеры диапазона усиления:

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

вам может понадобиться написать свой istreambuf_iterator, что тривиально .

0 голосов
/ 24 марта 2011

Мне кажется, что лучший ответ - написать пару ваших собственных итераторов, которые будут анализировать файл так, как вы хотите.Вы можете изменить std::vector<char> на std::vector<float> и использовать те же итераторы streambuf при условии, что входные данные были отформатированы как минимум с одним пробелом между значениями.

...