Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 150
Текст из файла (страница 150)
Однако реализация ввода/вывода — сложная и интересная задача. Ее решение содержит примеры, которые можно применить ко многигл другим задачам программирования и проектирования. Поэтому стоит изучить методы, использованные при реализации ввода/вывода. 1> этой главе обсуждается система вводаувывода в той степени, которая позволит вам оценить структуру этой системы, использовать ее для самых употребительных видов ввода/вывода и распространить ввод/вывод на работу с типами, определяемыми пользователем. Если вам понадобится реализовать стандартные потоки ввода,' вывода, ввести новый вид потока или учесть национальные особенности, вам понадобится копия стандарта, хорошее руководство по системе и/или примеры работающего кода в добавок к тем, что представлены здесь. Ключевые компоненты систем потокового ввода/вывода можно представить графически: 673 21.2.
Вывод 1ог Ьаге: независимглй от национальных особенностей формат состояния Ьиг1с гсгеатби7<>: буферизация Ьагсс саг<>: зависящий от национальных особенностей формат состояния состояниепотоха 1аса7г; информация о формате буфер символов непосредственно приемникуисточник 21.2. Вывод Безопасный с точки зрения типов и универсальный подход как к встроенным, так и к типам, определяемым пользователем, может быть достигнут с использованием единого перегруженного имени для набора функций вывода. Например: ри1 ~сггг, "х = ); О сеп — гта выходной поток сооби1еяий об ошибках ри1 (сегг, х~, ри1 (сгп, '~п1; Тип аргумента определяет, какая функция ри1 будет для него вызвана. Такое решение используется в некоторых других языках.
Однако, это приводят к повторениям. Перегрузка оператора «для обозначения «записать в» (рпс го) лает более удобное написание и позволяет программисту одной инструкцией выводить последовательность объектов. Например: сегг « "х = ' «х « '~п'; Если х относится к типу сп1 и нмеет значение Иа", такая инструкция выведет: х=12З Пунктирная стрелка от Ьагсс сог1геат<> показывает, что Ьаг1с сов<> является виртуальным базовым классом; сплошные стрелки представляют указатели.
Классы, помеченные <>, — это шаблоны, параметризованные символьным типом, содержащие национальные особенности. Концепция потоков и обеспечиваемая ей универсальная система обозначений могут быль применены к широкому классу задач, связанных с коммуникациями. Потоки используются для передачи объектов между компьютерами Я 25А.1), для шифровки сообщений в потоках Я 21.10[22)), для сжатия данных, для долговременного хранения обьектов и еще для очень многих целей. Однако рассмотрение их здесь ограничено только простым, ориентированным на символы вводом и выводом.
Объявления классов потоков ввода7вывода и шаблонов (достаточные для обращения к ним, но не достаточные для выполнения операций над ними) и стандартные определения типов 1рредеу'представлены в <1ог)тиИ>. Этот заголовочный файл порой требуется, когда вы хотите включить некоторые, но не все заголовочные файлы ввода7'вывода.
674 Глава 21, Потоки и далее переведет строку в стандартном потоке ошибок сегг. Подобным образом если х относится к типу сатр!ях !6 22.5) и >лмеет значение (1, 2.4), данное выражение выведет в сегг. х= (1, 24) Таким стилем можно пользоваться, если х относится к типу, для которого определен оператор «, а для нового типа оператор «пользователь может легко определить сам. Оператор вывода нужен для того, чтобы избежать многословности, которая получается при использовании функций вывода. Но почему именно «? Новый лексический знак придумать невозможно(6 11.2). Для ввода и вывода предлагалось использовать оператор пр>юваивания, но, кажется, болыпинство людей прелпочнтает разные операторы для ввода и для вывода. Кроме того, оператор = неправильно связывае>, то ссть сои1=а=Ь означает скорее сои!= (а-Ь), чем (сои!=а) =Ь Я 6.2).
Я пробовал < и >, но их смысл «меныпс чем» и «больше чем» так крепко врос в людские умы, что новые выражения, обозначающие ввод>вь>вод, для всех практических применений оказались просто нечитабельны. Операторы «и» используются для встроенных типов не так часто, чтобы вызвать проблему. Онп симметричны в том смысле, что могут использоваться для обозначения «в» и «из», Когда они применяются для ввода/вь>вода, я обращаюсь к « как к записить в, а к» вЂ” как к прочесть ия. Те, кто предпочитает более «технические» наименования, могут называть их соответственно инсертерак>и и экстрах>порик>и. Приоритет операции «не очень высок и позволяет вставлять арифметические выражения в операнды без скобок, Например: саи> « "а'Ьлс= ' «а*Ь+с «<>п'; Скобки нужно использовать при написании выражений с операторами, чей приори- тет ниже чем у « .
Например: саи>«'а Ь(с=" «(а Ь(с) «<>п'; Оператор сдвига влево Я 6,2.4) также можно использовать в выражении для вывода, по, конечно, он тоже должен писаться в скобках: сои1 « "а«Ь= "«(а«Ь) « "~п'; 21.2.1. Потоки вывода оя1геат — зто механизм для преобразования значений различного типа в последовательность символов. Обычно эти символы затем выводятся при помощи низкоуровневых операций вывода. Есть много видов символов Я 20.2), которые можно охарактеризовать при помощи свойств символов сйаг 1га!1я Я 20.2.1). Следовательно, оя1геат является специализапией для конкретных видов символов универсального п>аблона Ьая(с оя1геат: >етр1а1е<с1акя СЬ, с!аяк Тг= сьаг ггайя<СЬ» с!аяк я!>!<Ьак1с ак1геат: »1г>иа!риЫ1сЬая1с >ак<СЬ, Т> ( риЫ1с: илг>иа! -Ьак>с оя>геат (); 0- 675 21,2.
Вывод !урег(е/бал!с оз!сват<сбит> озггеат; гуре!!е/баз!с озггеат<еясбаг Г>гоояггеа; Во мнопгх системах запись расширенных символов можно оптимизировать посредством шоя!геат, но такая оптимизация плохо подойдет для потоков, где единицей ввода/вывода является байт Можно определить потоки, для которых физический ввод/вывод производится не в виде символов. Однако такие потоки находятся за пределами стандарта С++ и этой книги (З 21.10115)).
Базовый класс Ьая!с юя представлен в <гоя>. Он контролирует форматирование (6 21А), национальные особенности (6 21.7) и обращение к буфералг (6 21.6). Он такясе определяет несколько типов, служашнх для удобства записи: гетр!иге<с!аяя СИ, с1азя Тг= сбаг !гауз<СЬ» с!вяз згй:Ьаз!с гол. риЬдс гоя базе! риЫгс: !урейе/СЬ сбаг гуре, !урейе/Тг гтацз гуре; гурег!е/гурепате Тг:лп! гуре !п! гуре, // гпип целочисленного //значения символа гуреде/гуреггате Тгроз гуре роя гуре, //позиция в буфере гуре!!е/гурепате Тесова гуре оД гуре; // сжеигение в буфере //...
ою также: З" 2!.З.З, З 21.37, у 2!л!4, З 2!.бЗ и у 2!.7.1 Класс Ьая!с !оя запрещает копирующие конструктор гг присваивание Я 11.2.2). Со ответственно, потоки оя!геат и !я!геат нельзя копировать. Поэтому, если вам нужно изменить приемник потока, следует либо заменить буферы потоков (6 21.6А), либо воспользоваться указателями (2 1!.2,2). Класс юя Ьаяе содержит информацию и операции, не зависяшие от типа испскльзусмых символов — например, точность для вывода числа с плавающей точкой, Поэтому он не обязан быть шаблоном. Кроме определений !урес!е~в юя Ьаяе библиотека потоков ввода/вывода использует интегральный со знаком тип я!геатя!хе для представления размера буферов и числа символов, передаваемых в операциях ввода/вывода.
В <!оя!гент> объявлено несколько стандартных потоков: // стандартный силгвольный погпок вывода // стандартный небуферизованный поток вывода // для сообщений об ошибках // стандартный поток вывода для сообгцений об ошибках озб еат сои!; оз! еат сегг, оз!геат с1оу, //росгииренный поток, соответствугощий сои! // расгииренный поток, соответствуюгций сегг // расширенный гготок, соответсгпвггкггцггй с!оу гоозн еат госоиг, шоз! еат госегн шоз!геат гос!оу,' Этот шаблон н ассоциированные с пим операции вывода определены в пространстве имен я!с! и и редставлен ы заголовочным файлом <!оя!геат>. Параметры шаблона Ьаз!с !оя!гент контролируют используемый реагшзацией тип символов; они не влияют на возможные типы выводимых значений. Потоки, реализованные с использованием обычных сбаг, и те, что реализованы с использованием расширенных символов, непосредственно поддерживаются для каждой реализации: Глава 21.