Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Строковый итератор, несовместимый для чтения каждой строки

Автор вопроса: Walter Fabio SimoniОтветов: 1

У меня есть std::ostringstream. Я хотел бы выполнить итерацию для каждой строки этого std::ostringstream.

Я использую boost::tokenizer :

std::ostringstream HtmlStream;
.............
typedef boost::tokenizer<boost::char_separator<char> > line_tokenizer;
line_tokenizer tok(HtmlStream.str(), boost::char_separator<char>("\n\r"));

for (line_tokenizer::const_iterator i = tok.begin(), end = tok.end(); i != end; ++i)
{
    std::string str = *i;
}

На линии

for (line_tokenizer::const_iterator i = tok.begin(), end = tok.end(); i != end;

У меня есть ошибка утверждения с "несовместимым строковым итератором". Я читал об этой ошибке в Google и в StackOverflow, но мне трудно найти свою ошибку.

Кто-нибудь может мне помочь, пожалуйста?

Большое спасибо,

С наилучшими пожеланиями,

Никсеус

  • Поскольку вы, кажется, не возражаете против копии, как насчет того, чтобы скопировать str() в istringstream и использовать std::getline()? Chad 03.12.2013
  • Я новичок в мире boost::, поэтому мне нужно его изучить! Не могли бы вы дать мне пример кода для этого примера? С iStringStream? Спасибо :) Walter Fabio Simoni 03.12.2013
  • @WalterFabioSimoni: я думаю, что Чад имеет в виду создать экземпляр std::istringstream, инициализированный вашей строкой, а затем использовать с ним std::getline() так же, как и файловый поток. Это позволит избежать использования Boost в целом. Это может сработать для вас, но оно не может делать все, что может делать boost::tokenizer (например, игнорировать последовательные символы-разделители). Fred Larson 03.12.2013

c++stringboostassertboost-tokenizer

Ответы

Ответ 1 · рейтинг 2 · sehe

Мне нравится делать это без копирования для отчетов об эффективности/ошибках:

Смотрите Прямой эфир на Coliru

#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <iostream>
#include <vector>

int main()
{
    auto const& s = "hello\r\nworld";

    std::vector<boost::iterator_range<char const*>> lines;
    boost::split(lines, s, boost::is_any_of("\r\n"), boost::token_compress_on);

    for (auto const& range : lines)
    {
        std::cout << "at " << (range.begin() - s) << ": '" << range  << "'\n";
    };
}

Отпечатки:

at 0: 'hello'
at 7: 'world'

Это более эффективно, чем большинство показанных альтернатив. Конечно, если вам нужны дополнительные возможности парсинга, рассмотрите Boost Spirit:

Смотрите Прямой эфир на Coliru

#include <boost/spirit/include/qi.hpp>

int main()
{
    std::string const s = "hello\r\nworld";

    std::vector<std::string> lines;

    {
        using namespace boost::spirit::qi;
        auto f(std::begin(s)),
             l(std::end(s));
        bool ok = parse(f, l, *(char_-eol) % eol, lines);
    }

    for (auto const& range : lines)
    {
        std::cout << "'" << range  << "'\n";
    };
}

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы