C ++ - Как восстановить istream, если не удалось самостоятельно определить экстрактор

0

Мне нужен самонастраиваемый экстрактор (оператор >>), чтобы прочитать определенную строку в моем собственном типе данных.

Проблема в том, что требования к строке большие.

Следовательно, самый простой способ - это, вероятно, прочитать всю строку из istream, а затем проверить, выполнены ли все требования.

Моя проблема в том, что строка недействительна. Насколько мне известно, в C++ распространено, что поток не изменяется.

Какова наилучшая практика для восстановления istream в этом случае? Является ли обработка исключений в следующем примере достаточной?

std::istream& operator>>(std::istream& is, Foo& f)
{
    std::string str;

    if (is >> str)
    {
        // check if string is valid
        if ( is_valid( str ) )
        {
            // set new values in f
        }
        else
        {
            // recover stream
            std::for_each(str.rbegin(), str.rend(),
                          [&] (char c)
            {
                is.putback(c);
            });

            // ste failbit
            is.clear(std::ios_base::failbit);
        }
    }

    return is;
}

А как насчет std :: getline(), а не >> str? Есть ли другие подводные камни?

благодаря

Marco

  • 1
    Нет, нет способа восстановить поток в его начальное состояние, если поток не поддерживает (неограниченное) многократное возврат или обратный поиск.
Теги:
io
stream
recovery

1 ответ

0
Лучший ответ

Вы не можете вернуть потоки в исходное положение, где вы начали читать, по крайней мере, не в общем. Теоретически вы можете поместить обратные символы или искать место, где вы были раньше, но многие потоковые буферы не поддерживают возврат символов или поиск. Стандартная библиотека дает некоторое ограниченное руководство, но она имеет дело с довольно простыми типами, например целыми числами: символы читаются до тех пор, пока формат соответствует, и он останавливается именно там. Даже если формат соответствует, могут быть некоторые ошибки, которые могли быть обнаружены ранее.

Вот тестовая программа, демонстрирующая стандартное поведение библиотеки:

#include <iostream>
#include <sstream>

void test(std::string const& input)
{
    std::istringstream in(input);
    int i;
    std::string tail;

    bool result(in >> i);
    in.clear();
    std::getline(in, tail);
    std::cout << "input='" << input << "' "
              << "fail=" << std::boolalpha << result << " "
              << "tail='" << tail << "'\n";
}

int main()
{
    test("10 y");
    test("-x y");
    test("0123456789 x");
    test("123456789012345678901234567890 x");
}

Чтобы объяснить четыре тестовых примера:

  1. Просто чтобы убедиться, что тест делает то, что он предназначен, первый вход на самом деле в порядке, и проблем нет.
  2. Второй ввод начинается с символа, соответствующего формату, за которым следует что-то не совпадающее, а чтение останавливается сразу после символа '-'.
  3. Третий тест читает int используя восьмеричные числа. Ошибка могла быть обнаружена на символе '8' но и '8' и '9' потребляются, и вход не работает.
  4. Последний пример приводит к переполнению, которое может быть обнаружено до того, как все цифры будут прочитаны, но все цифры будут прочитаны.

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

  • 0
    Спасибо, кажется, я был немного трек с точки зрения потоков ввода-вывода ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню