Ввод Типов, Определяемых Пользователем
Ввод для пользовательского типа может определяться точно так же, как вывод, за тем исключением, что для операции ввода важно, чтобы второй параметр был ссылочного типа. Например:
istream operator(istream s, complex a) /* форматы ввода для complex; "f" обозначает float: f ( f ) ( f , f ) */ { double re = 0, im = 0; char c = 0;
s c; if (c == '(') { s re c; if (c == ',') s im c; if (c != ')') s.clear(_bad); // установить state } else { s.putback(c); s re; }
if (s) a = complex(re,im); return s; }
Несмотря на то, что не хватает кода обработки ошибок, большую часть видов ошибок это на самом деле обрабатывать будет. Локальная переменная c инициализируется, чтобы ее значение не оказалось случайно '(' после того, как операция окончится неудачно. Завершающая проверка состояния потока гарантирует, что значение параметра a будет изменяться только в том случае, если все идет хорошо.
Операция установки состояния названа clear() (очистить), потому что она чаще всего используется для установки состояния потока заново как _good. _good является значением параметра по умолчанию и для istream::clear(), и для ostream::clear().
Над операциями ввода надо поработать еще. Было бы, в частности, замечательно, если бы можно было задавать ввод в терминах шаблона (как в языках Снобол и Икон), а потом проверять, прошла ли успешна вся операция ввода. Такие операции должны были бы, конечно, обеспечивать некоторую дополнительную буферизацию, чтобы они могли восстанавливать поток ввода в его исходное состояние после неудачной попытки распознавания.