Используйте boost :: tokenizer с boost :: iterator_range

я использую boost::tokenizer прочитать CSV-подобный файл. Я храню токены в std::vector, Это хорошо работает, но я хочу хранить только boost::iterator за каждый токен.

Я старался:

#include <string>
#include <boost/tokenizer.hpp>
#include <boost/range/iterator_range.hpp>

typedef std::string::const_iterator string_iter;
typedef boost::iterator_range<string_iter> string_view;

int main(){
std::string line;

std::vector<string_view> contents;

boost::tokenizer<boost::escaped_list_separator<char>, string_iter, string_view> tok(line.begin(), line.end());
contents.assing(tok.begin(), tok.end());
}

Но он не компилируется:

/usr/include/boost/token_functions.hpp: создание экземпляра ‘bool
повышение :: escaped_list_separator :: оператор () (InputIterator&, InputIterator, токен&) [с
InputIterator = __gnu_cxx :: __ normal_iterator>; Токен =
повышение :: iterator_range<__gnu_cxx :: __ normal_iterator>>; Char = char; Черты =
std :: char_traits] ’: /usr/include/boost/token_iterator.hpp:70:11:
требуется от boost void boost :: token_iterator :: initialize () [с TokenizerFunc =
повышение :: escaped_list_separator; Итератор =
__gnu_cxx :: __ normal_iterator>; Type = boost :: iterator_range<__gnu_cxx :: __ normal_iterator>>] ’
/usr/include/boost/token_iterator.hpp:77:63: требуется от
‘Boost :: token_iterator :: token_iterator (TokenizerFunc, Iterator, Iterator) [с
TokenizerFunc = boost :: escaped_list_separator; Итератор =
__gnu_cxx :: __ normal_iterator>; Type = boost :: iterator_range<__gnu_cxx :: __ normal_iterator>>] ’/usr/include/boost/tokenizer.hpp:86:53:
требуется от ‘boost :: tokenizer :: iter
boost :: tokenizer :: begin () const [с
TokenizerFunc = boost :: escaped_list_separator; Итератор =
__gnu_cxx :: __ normal_iterator>; Type = boost :: iterator_range<__gnu_cxx :: __ normal_iterator>>; boost :: tokenizer :: iter =
повышение :: token_iterator,
__gnu_cxx :: __ normal_iterator>, boost :: iterator_range<__gnu_cxx :: __ normal_iterator>>>] ’
/home/wichtounet/dev/gooda-to-afdo-converter/src/gooda_reader.cpp:58:37:
отсюда требуется /usr/include/boost/token_functions.hpp:187:16:
ошибка: нет совпадения для оператора + = в tok + = (&
следующая) -> __ gnu_cxx :: __ normal_iterator<_Iterator,
_Container> :: operator *> () ’/usr/include/boost/token_functions.hpp:193:11: ошибка: не соответствует
‘Оператор + =’ в ‘ток + = (&
следующая) -> __ gnu_cxx :: __ normal_iterator<_Iterator,
_Container> :: operator *> () ’/usr/include/boost/token_functions.hpp: в экземпляре‘ void
повышение :: escaped_list_separator :: do_escape (итератор&,
итератор, токен&) [with iterator = __gnu_cxx :: __ normal_iterator>; Токен =
повышение :: iterator_range<__gnu_cxx :: __ normal_iterator>>; Char = char; Черты =
станд :: char_traits]:
/usr/include/boost/token_functions.hpp:176:11: требуется от ‘bool
повышение :: escaped_list_separator :: оператор () (InputIterator&, InputIterator, токен&) [с
InputIterator = __gnu_cxx :: __ normal_iterator>; Токен =
повышение :: iterator_range<__gnu_cxx :: __ normal_iterator>>; Char = char; Черты =
std :: char_traits] ’/usr/include/boost/token_iterator.hpp:70:11:
требуется от boost void boost :: token_iterator :: initialize () [с TokenizerFunc =
повышение :: escaped_list_separator; Итератор =
__gnu_cxx :: __ normal_iterator>; Type = boost :: iterator_range<__gnu_cxx :: __ normal_iterator>>] ’
/usr/include/boost/token_iterator.hpp:77:63: требуется от
‘Boost :: token_iterator :: token_iterator (TokenizerFunc, Iterator, Iterator) [с
TokenizerFunc = boost :: escaped_list_separator; Итератор =
__gnu_cxx :: __ normal_iterator>; Type = boost :: iterator_range<__gnu_cxx :: __ normal_iterator>>] ’/usr/include/boost/tokenizer.hpp:86:53:
требуется от ‘boost :: tokenizer :: iter
boost :: tokenizer :: begin () const [с
TokenizerFunc = boost :: escaped_list_separator; Итератор =
__gnu_cxx :: __ normal_iterator>; Type = boost :: iterator_range<__gnu_cxx :: __ normal_iterator>>; boost :: tokenizer :: iter =
повышение :: token_iterator,
__gnu_cxx :: __ normal_iterator>, boost :: iterator_range<__gnu_cxx :: __ normal_iterator>>>] ’
/home/wichtounet/dev/gooda-to-afdo-converter/src/gooda_reader.cpp:58:37:
здесь требуется /usr/include/boost/token_functions.hpp:130:9:
ошибка: нет совпадения для оператора + = в tok + = ‘\ 012’
/usr/include/boost/token_functions.hpp:134:9: ошибка: не соответствует
‘Оператор + =’ в ‘ток + = (&
следующая) -> __ gnu_cxx :: __ normal_iterator<_Iterator,
_Container> :: operator *> () ’/usr/include/boost/token_functions.hpp:138:9: ошибка: не соответствует
‘Оператор + =’ в ‘ток + = (&
следующая) -> __ gnu_cxx :: __ normal_iterator<_Iterator,
_Container> :: operator *> () ’/usr/include/boost/token_functions.hpp:142:9: ошибка: не соответствует
‘Оператор + =’ в ‘ток + = (&
следующая) -> __ gnu_cxx :: __ normal_iterator<_Iterator,
_Container> :: operator *> () ’

Я также просто попытался вычислить два итератора самостоятельно, используя boost::token_iterator, но я пока не добился успеха.

Есть ли решение получить только диапазон итераторов для каждого токена вместо строки, чтобы сохранить некоторые характеристики?

2

Решение

Это не может работать. tokenizer ожидает тип (третий аргумент шаблона), к которому можно добавить результаты функции токенизатора. В частности, он должен предоставить оператору += ( tokenizer<...>::iterator::value_type ), фрагмент кода Ниже следует сделать еще один шаг вперед, хотя я не уверен, стоит ли это усилий …

#include <string>
#include <boost/tokenizer.hpp>
#include <boost/range/iterator_range.hpp>
#include <iostream>
#include <cstddef>

typedef std::string::const_iterator string_iter;
typedef boost::iterator_range<string_iter> string_view;

// a constant size character buffer, skips anything beyond CSize...
template< std::size_t CSize >
class assignable_view {
std::size_t m_size;
char m_buffer[CSize];

friend std::ostream& operator << (std::ostream& p_out, assignable_view const & p_view)
{
if (p_view.m_size > 0u) {
std::copy(p_view.m_buffer, p_view.m_buffer + p_view.m_size, std::ostream_iterator<char>(p_out));
}
return p_out;
}

public:
template <class TIter>
void operator += (TIter p_input)
{
if (m_size < CSize) {
m_buffer[m_size++] = p_input;
}
}
assignable_view()
: m_size(0u) {}
};

int main(){
std::string line
= "Field 1,\"putting quotes around fields, allows commas\",Field 3";

std::vector<string_view> contents;

boost::tokenizer<
boost::escaped_list_separator<char>,
string_iter,
assignable_view<11>
> tok(line.begin(), line.end());

for (auto const & t_s : tok) {
std::cout << t_s << std::endl;
}
//contents.assing(tok.begin(), tok.end());
}
3

Другие решения

Ах! Вам нужно включить:

#include <iostream>
#include <boost/tokenizer.hpp>
#include <boost/range/iterator_range.hpp>
#include <string>

int main()
{
std::string line;
typedef std::string::const_iterator string_iter;
typedef boost::iterator_range<string_iter> string_view;

boost::tokenizer<boost::escaped_list_separator<char>, string_iter, string_view> tok(line.begin(), line.end());
}

компилирует нормально

3