io — как восстановить istream, если не удалось самостоятельно определить экстрактор

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

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

Следовательно, возможно, самый простой способ — прочитать всю строку из 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 () вместо is >> str? Есть ли другие подводные камни?

Спасибо

Marco

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

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


По вопросам рекламы [email protected]