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