Модифицировать значение перед добавлением std::ostream_iterator

278
19 октября 2017, 11:00

Есть строка формата 1,-1,5,2,9,.... Нужно превратить ее в std::list<int>.

std::istringstream iss{raw_data};
std::list<int> data{};
using ISIt = std::istream_iterator<std::string>;
std::copy(ISIt{iss}, ISIt{}, std::ostream_iterator<int>(data, ',')); // Не правильно

Очень элегантное решение, но одна проблема. Как превратить строку в число перед тем, как его получит std::ostream_iterator? Думал унаследоваться от него, переопределив метод operator=, но ввиду того, что данный метод не виртуальный, то при объектом полиморфизме внутри std::copy все равно будет вызываться метод базового класса.
Да и наследование порождает много ненужного кода.

Есть ли элегантное решение данной проблемы?

Answer 1

Если идти по тому же пути, т.е. использовать istringstream, copy, istream_iterator, то можно сделать свой фасет, в котором запятая будет "определена" как разделитель, для того, чтобы поток мог разбить числа через пробелы и через запятые. Не знаю, удовлетворяет такое решение требованиям элегантности или нет.

#include <iostream>
#include <locale>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <list>

struct my_facet : std::ctype<char>
{
    using parent_t = std::ctype<char>;
    my_facet(std::size_t refs = 0): parent_t(make_table(), false, refs) {}
    static const mask* make_table()
    {   
        static mask char_table[table_size];
        static int fake = (std::copy(classic_table(), classic_table() + table_size, char_table), (void)fake, 0);
        char_table[','] |= space;//Запятая теперь разделитель
        return char_table;
    } 
};

std::list<int> make_list(const std::string &source)
{
    std::istringstream ss(source);
    ss.imbue(std::locale(ss.getloc(), new my_facet()));//Цепляем наш фасет к потоку
    std::list<int> result;
    std::copy(std::istream_iterator<int>(ss), std::istream_iterator<int>(), std::back_inserter(result));
    return result;
}

int main()
{
    for (auto e: make_list("1,-1,5,2,9")) {
        std::cout << e << ";";
    }
}
READ ALSO
Вектор векторов строк

Вектор векторов строк

Имеется класс со структурой и полями:

351
Игнорирование условия в While С++

Игнорирование условия в While С++

Задание такое: заполнить матрицу Nного порядка и посчитать

286
Разница между функциями wsprintfW() и swprintf_s()

Разница между функциями wsprintfW() и swprintf_s()

Собственно не могу понять в чем же разница между 2мя этими функциями, когда они дают идентичные результаты

332