Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 153
Текст из файла (страница 153)
Ввод обрабатывается почти так же, как вывод. Имеется класс 1язгеат, который предоставляет операцию» («прочесть из») для небольшого набора стандартных типов. Можно определять эту операцию для любых пользовательских типов. 2).3. Ввод 21.3.2. Ввод встроенных типов Класс 1зьгеат определяет операцию» для встроенных типов: !етр(а!е<с(ая СЬ, с!азв Тг = сааг гга(в<СЬ» с!ат Ьаяс 1з!геат: Ыг(иа! риЫ(с Ьазк 1оз<СЬ, Тг> ( риЫ1с: У ... Р форматированный ввод: ьазк вггеать орегагог» (зьоть и); Ьаяс (з!геать орега!ог» ((п(ь и); Ьаяс 1з!геать орегагог» (1опдь и); Ьаяс !за вать орега!ог» (ипядпеИ зЬог!ь и); Ьаяс Ваеать орега!ог» (ипз!дпе4 шгь и); Ьаяс !з!геать орегагог» (ипз(дней 1опдь и); Ьаяс !Зггеат ь орегагог» ~Яоа!ьЯ ! Ьазк В(геат ь орегагог» (4оиЫеь 3); Ьаяс Впеать.орега!ог» (1опд 4оиЫеь Л Ьаяс 1зггеат ь орегагог» (Ьоо(ь Ь); Ьазк Вггеать орега(ог» (ио14*ь р); У...
)' Функции орега!ог» () определяются в следующем стиле: воеат ь тягеат;: орега!ог» ( ть згаг) У Т- это тип, длл которого обьлвллется ВЛ еат::орегагог' > ( (г пропустить пробельные символы, затем прочитать значение типа Т в (наг ге!игп *!Ыз! ) Поскольку операция» пропускает пробельные символы, вы можете читать последовательность целых чисел, разделенных такими символами, следующим образом: 1пггеа4 1пв(гес!ог<т!>ь г) дзаполнение и возврат числа прочитанных!и! ( 1п!г = О! ыЬде ( 1< г. яье ( ) ь ь с(п» г [1) ) (ч ь ! ге!иго 1; ) Нецелые на входе приведут к окончанию чтения.
Например, если на вход поступят 123 45.6 78. функция геаг! 1пв() прочтет пять целых чисел: 11345 и оставит точку для последующего чтения. Пробельные символы соответствуют таковым в языке С (пробел, табуляция, новая строка, новая страница и возврат каретки) и распознаются функцией 1лврасе(), определенной в <сс!уре> (В20.4.2). 728 Глава 2).
Потоки По умолчанию, операция» пропускает пробельные символы. Но мы можем изменить такое поведение: я. иия(Т(!ат (иве:: ьйгрив) заставит операцию» для и трактовать пробельные символы так же, как обычные символы (см, в21.4.1, в21.4.6 и в21.4.6.2). Применяя !зггеат, часто совершают следующую типичную ошибку; не замечают, что фактически введено было не то, что ожидалось (например, из-за подачи на вход потока символ неожиданного формата). Нужно или проверять состояние потока ввода (521.3.3) перед тем, как использовать то, что бьшо предположительно введено, или задействовать исключения (521.3.6).
Ожидаемый на входе формат определяется текущими установками локализации (В2!.7), По умолчанию, логические значения ггие и Га!ье представляются как 1 и О, соответственно. Целые числа должны представляться в десятичном формате, а числа с плавающей запятой должны иметь тот формат, какой принят в языке С++. Установив ЬазеЯеЫ 621.4.2), можно прочесть 0123 как восьмеричное число с десятичным значением 83, а Ох9"как шестнадцатеричное число с десятичным значением 255. Формат, по которому читаются значения для указателей, целиком зависит от конкретной реализации (проверьте, как это делается в вашей реализации). Удивительно, но для чтения символов функции-члена, соответствующей операции», нет. Зато для этого есть функция-член ае!() Я21.3.4), и поэтому нет никакой необходимости определять такую операцию» в качестве функции-члена.
Из потока мы можем прочитать символ в связанный с потоком символьный тип. Если это сйаг, то мы можем прочесть символ и в яапеь! сйаг, и в ипь!япеО сйаг: гетрйпе<сйяь Сй, с!аье Тг> Ьаяс !ягеат<СЬ, Тг>ь орегагог» (Ьаяс !зггеат<СЬ, Тг>ь, Сйь); гетр1а!с<с!ат Тг> Ьаяс !ыгеат<сйаг, Тг>ь орега<ог» (Ьае!с йггеат<сйаг, Тг>ь, иие!аией сйагь); !етр!а!е<с!ат Тг> Ьаяс !еггеат<сйаг, Тг>ь орега!ог» (Ьаяс !е!геат<сйаг, Тг> ь, е!аиеИ сйагь); С точки зрения пользователя не важно, определена ли операция» с помощью функции-члена, или нет. Как и в остальных операциях», здесь также сначала пропускаются пробельные символы.
Например: гоЫ Т() сйаг с; с(и» с; !! ... ) Таким образом, в переменную с попадет первый символ из с!п, не являющийся разделительным (пробельным) символом. Кроме того, можно читать и в массив символов: гетр!а!с<с!пес Сй, с1ат Тг> Ьаяс !ягеат<Сй, Тг>ь орегагог» (Ьаь!с !ягеат<СЬ, Тг>ь, Сй*); гетр1аге<с1ат Тг> Ьаяс !еггеат<сйаг, Тг>ь орегагог» (Ьаяс !ьггеаиь<сйаг, Тг>ь, иияеиег) сйаг*); гетр1аге<с1ат Тг> Ьаз!с !ягеат<сйаг, Тг>ь орегагог» (Ьаяс 1игеат<сйаг, Тг>ь, е!апет сйаг*); 21.3. Ввод гоЫ о() ( сдаг г(41; ст .
тЫгд (4); с(п » ю сонг« "г = " «г «еп41; Здесь в в будет прочитано самое большее три символа и завершающий нуль. Вызов функции иЫ1Ь () для потока Ыв еагп влияет лишь на следующую за этим операцию чтения» в массив, и не влияет на считывание в иные типы переменных. 21.3.3. Состояние потока Каждый поток ((в«еат или ов«еат) характеризуется своим состоянием (в(ага). Проверкой состояния потока можно выловить ошибки и нестандартные положения.
С состоянием потока работает класс Ьаяс Ьт из <йм>, базовый для класса Ьав(с 1в«еат: гетр(аге<с1авв СЬ, с1авв Тг = сбег гга(гв<СЬ» с(авв Ьаяс (ов: риЫ(с 1ов Ьаве ( риЫ1с: // ... Ьоо1 аоод ( ) сопл« Ьоо! ео1'() сопл« Ьоо11а11() сопво Ьоо1 Ьад() сопвп //след. операция может быть выполнена /Увиден конец ввода //след. операция не может быть выполнена // поток испорчен (овгаге где(иге () сопл(; /У получить флаги состояния ввода/вывода иоЫ с(еаг ((овгаге1 = доодЬИ); //установить флаги состояния (/о гоЫ ве«яаге ((овса<в 1) ( с1еаг (где(иге () (1); ) // добавить ( к флагам состояния 1/о /У не нуль, если (гой() орегагог гоЫ* () сопя; Ьоо( орегагог! () сопл( (ге/ига)а(1 (); ) // .. Если дооИ() возвращает «ие, то предыдущая операция ввода завершилась успешно и может выполняться следуюшая операция ввода; в противном случае следуюшая операция ввода не пройдет — это просто нулевая операция, так что попытка ввода в переменную о оставляет переменную в без изменения (если у имеет тип, для которого имеются функции-члены классов Ы«еат и ов«еат).
Разница между состояниями 1а11( ) и Ьаь(() невелика — в первом случае считается, что поток не ис- Эти операции также пропускают пробельные символы. Затем они считывают символы из потока в массив-операнд до тех пор, пока не встретится пробельный символ или конец файла. В конце концов, они завершают строку нулем. Ясно, что это открывает лазейку для переполнения, так что лучше читать в ввчпд (520.3.15). В то же время, можно ограничить число читаемых операцией» символов: Ьц пЫгЬ(п) устанавливает, что последуюшая операция» над Ы прочтет в массив максимум и-1 символ. Например: Глава 2).
Потоки порчен (возможно просто потеряны символы), во втором же случае ничего определенного сказать нельзя. Состояние потока представляется набором флагов. Как и большинство констант, характеризующих поведение потоков, эти флаги определяются в !ов Ьаве— базовом классе для Ьаяс юк сгазз юв Ьазе ( риЫзс: // ...
зуредеГ зтр1етепгатзоп аеузпеа2 !отазе; ззабс сопл! зов!а(е Ьаабгг, ео/Ы1, уа!!В!1, Лооаб!г; /У поток испорчен // виден конец файла //следуюзцая операция не будет выполнена /У иоодб!!= =О Флагами состояния ввода/вывода можно манипулировать непосредственно.
Например: ио)а 1" ( ) ( !ов Ьазе::1отаге в = сзп.п!в!иге(); рвоэвраи(оет набор битов состояния ввода/вывода (1 (в а юз бале::Ьадб!1) ( //возможно, лри вводе потеряны символы ) /7... ст. веьиоте (!ов Вазе::/а!!Ь!1) з // ... ) гетр!а!в<с!от Т> гоЫ зосору (Ыи вата Ы, озиеать ов) ( Т Ьиуз ыб!1е(1з»бий «бцТ« ' 'тп'; Выражение !в»Ьиг"возвращает ссылку на Ы, и состояние последней проверяется неявным вызовом !зггеат:: орегагог во!И" () . Функцию юсору () можно использовать следующим образом: коЫ/'(!в!сеато 11, и!сеато 12, !тагеать 13, бзиеать з4) ( зосору<сотр1ех> (з1, сои!); 1осору<аоиЫе> (!2, сои!); //копирование чисел типа сотр!ех /У копирование чисел типа т!оиб!е Когда поток используется в качестве условия, состояние потока проверяется фуНКцИяМИ ОрЕЗагОГ кОЫ* () ИЛИ ОрЕГагОГ( () .
Этн ПрОВЕрКИ ВОЗВращаЮт 1ГиЕ ТОЛЬКО тогда, когда состояние потока есть )уи!!() или 1а!!(), соответственно. Например, универсальную функцию копирования можно написать так: 23) 21.3. Ввод )осору<сйаг> (13,сои() ( //копирование чисел типа сйаг !агору<в(г!ие> ((ч, сои() ( У копирование слов, разделенны пробельными символами ) 21.3.4. Ввод символов (етр!а(е<с(азз СЬ, с(ая Тг = сйаг (га)ь<СЬ» с1азз Ьаяс (з(геат: г!г(иа1 риЫ!с Ьаз(с !оз<СЬ, Тг> ( риЬ1(с( // ... // неформатированный ввод: з(геатз(зе есоип(О сопл(( //число символов, прочитанных последней функцией // неформатированного ввода У чтение одного СЬ (или Тгкео~()) /У чтение одного СЬ в с (п( (уреее(() ( ьаяс в(геать де((сьь с) Ьаяс (з(геать ее((СЬ* р, з(геатз((е и) ( //терминатор - новая строка Ьаяс (з(геатз ле((СЬ* р, ей еатз!зе и, СЬ (ест ) ( Ьаяс Виват з ее(1(пе (СЬ* р, зй еатя(е и ) ( // терминатор - новая строка Ьаз1с (з(геатз ее(1!ие (СЬ* р, зйеатязе п, СЬ (егт) ( Ьаяс Вегеать (епоге(з(геатз!зе и = 1, т( (уре (= Тг(:ео1'() ); Ьаяс !з(геатз геа(((СЬ* р, з(геатз((е и) ( //чтение не более п символов // ...
)( Кроме того, в заголовочном файле <з(г!пя> имеется функция ее(11пе () для стандартного типа з(г!пе (В20.3.15). Функции неформатированного ввода не пропускают пробельных символов. Если функции яе(() или яе(1!пе () не читают и не удаляют из потока ни одного символа, вызывается зе(зта(е(уа!1Ь!() и все последующие попытки чтения из потока закончатся неудачей (илн будет сгенерировано исключение; В21.3.6). Функция яе((сйагз) считывает один символ в свой аргумент. Например: (п( та(п ( ) ( сваг с( (гй((е(с!п.ее((с) ) сои(.ри((с) ) Функция с тремя аргументами з.ле((р, п,(егт) читает не более и-1 символов в р(О] ..р(п-2]. Вызов «е(() всегда помещает О после помещенных в массив р(] символов, так что р должен указывать на массив, содержащий не менее п символов.