Мне нужен самонастраиваемый экстрактор (оператор >>), чтобы прочитать определенную строку в моем собственном типе данных.
Проблема в том, что требования к строке большие.
Следовательно, самый простой способ - это, вероятно, прочитать всю строку из 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
Вы не можете вернуть потоки в исходное положение, где вы начали читать, по крайней мере, не в общем. Теоретически вы можете поместить обратные символы или искать место, где вы были раньше, но многие потоковые буферы не поддерживают возврат символов или поиск. Стандартная библиотека дает некоторое ограниченное руководство, но она имеет дело с довольно простыми типами, например целыми числами: символы читаются до тех пор, пока формат соответствует, и он останавливается именно там. Даже если формат соответствует, могут быть некоторые ошибки, которые могли быть обнаружены ранее.
Вот тестовая программа, демонстрирующая стандартное поведение библиотеки:
#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");
}
Чтобы объяснить четыре тестовых примера:
'-'
.int
используя восьмеричные числа. Ошибка могла быть обнаружена на символе '8'
но и '8'
и '9'
потребляются, и вход не работает.Исходя из этого, я бы подумал, что не ожидается ожидание сброса потока в исходную позицию, когда проверка семантики на правильно сформированном входе не будет выполнена.