Реферат: Turbo C++ Programer`s guide
Использование потоков 2.0
Усовершенствованные потоки iostream версии 2.0,
хотя и обеспечивают по большей части совместимость для старой версии С++,
предлагают тем не менее новые возможности, связанные с использованием
множественного наследования и прочими средствами, появившимися в С++ версии
2.0.
Обсуждение различий между старыми потоками и новыми потоками, а также
основы преобразования старых потоков в новые см. в разделах
"Использование старых потоков" и "Основы перехода к потокам
версии 2.0" в конце настоящей главы.
Концепция потоков С++ нацелена на решение нескольких проблем,
решаемых стандартными библиотечнымифункциями ввода/ вывода С, такими какprintfи
scanf. Последние, разумеется остаются доступными для программиста, работающего
в С++, но улучшенная гибкость и элегантность потоков С++ уменьшают
привлекательность функций библиотеки stdio.h. Классы, связанные с потоками С++,
предлагают вам расширяемые библиотеки, позволяющие вам выполнять
форматированный ввод/выводс контролемтипов какдля предопределенных, так и для
определяемых пользователем типов данных спомощью перегруженных операцийи прочих
объектно-ориентированных методов.
Для обращения к вводу/выводу потоком ваша программа должна
включать файл iostream.h. Для некоторых функций потоков требуются и другие
файлы заголовка. Например, для выполнения форматирования в оперативной памяти с
использованием классов istrstream и ostrstream необходим файл strstream.h. Файл
заголовка strstream.h включает также iostream.h. Если вам требуется класс
fstream, включите файл fstream.h,такжевключающий iostream.h. И разумеется,
можно включить одновременно и fstream.h, и strstream.h.
Что такое поток?
Потоком называется абстрактное понятие, относящееся
к любому переносу данных от источника (или поставщика данных) к приемнику (или
потребителю) данных. Также используются синонимы извлечение, прием и получение,
когда речь идет о вводе символов от источника, и вставка, помещение или
запоминание, когда речь идет о выводе символов на приемник.
Несмотря на свое имя, класс потока может быть использован
для форматирования данных в ситуациях, не подразумевающих реального выполнения
ввода/вывода. Вы увидите, что форматирование в памяти можно применять к
символьным массивам и прочим структурам.
Библиотека iostream
Библиотека iostream имеет два параллельных класса: streambuf и ios. Оба
они являются классами низкого уровня и каждый выполняет свой круг задач.
streambuf
Класс streambufобеспечивает общие правила
буферизации и обработки потоков в тех случаях, когда не требуется значительного
форматирования этих потоков. streambuf представляет собой удобный базовый
класс, используемый другими частями библиотеки iostream, хотя он доступен также
и для производных классов в ваших функциях и библиотеках. Большинство
функций-компонентов (правил) streambuf являются встраиваемыми для обеспечения
максимальной эффективности. Классы strstreambuf и filebuf являются производными
от streambuf.
ios
Класс ios (и следовательно, производные от него классы) содержит
указатель на streambuf.
ios имеет два производных класса: istream (для ввода) и
ostream (для вывода). Другой класс, iostream, является производным классом
сразуот istream иostream вследствие множественного наследования:
class ios;
class istream
: virtual public ios;
class ostream
: virtual public ios;
classiostream : public istream,
public ostream;
Кроме того, существуеттри класса withassign, являющихся производными
классами от istream, ostream и iostream:
class
istream_withassign : public istream;
class
ostream_withassign : public ostream;
class iostream_withassign :
public iostream;
Классы потоков
- Класс ios содержит переменные состояния для интерфейса с streambuf и
обработки ошибок.
- Класс istream поддерживает как форматированные, так и неформатированные
преобразования потоков символов, извлекаемых из streambuf.
- Класс ostream поддерживает как форматированные, так и
неформатированные преобразования потоков символов, помещаемых в streambuf.
- Класс iostream объединяет классы istream и ostream для
двунаправленных операций, в которых один поток действует и как источник, и как
приемник.
- Производные классы withassign обеспечивают четыре
предопределенных "стандартных" потока: cin, cout, cerr и clog,
описываемые в следующем разделе. Классы withassign добавляют к соответствующим
базовым классам операции присвоения, следующим образом:
class
istream_withassign : public istream (*
istream_withassign();
istream&
operator=(istream&);
istream&
operator=(streambuf*);
*)
и аналогично для ostream_withassign и
iostream_withassign.
Классом потока называется любой класс, производный
от классов istream и ostream.
Четыре стандартных потока
Программы С++ начинаются с четырьмя
предопределенными открытыми потоками, объявленными как объекты классов
withassign в iostream.h следующим образом:
extern
istream_withassign cin;
extern
ostream_withassign cout;
extern
ostream_withassign cerr;
extern ostream_withassign clog;
Их конструкторывызываются всякий раз при включении
iostream.h, но фактическая инициализация выполняется только один раз.
Четыре стандартных потока
выполняют следующее:
cin Стандартный
ввод (дескриптор файла 0)
(Соответствует stdin)
cout Стандартный вывод (дескриптор файла 1)
(Соответствует stdout)
cerr Стандартный вывод ошибок (дескриптор файла 2). cerr
буферизуется поблочно; очистка буфера происходит при каждой новой вставке
(Соответствует stderr)
clog Данный поток представляет собой полностью
буферизуемую версию cerr.
Как и в С, вы можете переназначить эти стандартные имена
на другие файлы или символьные буферы после загрузки программы.
Вывод
Вывод потока осуществляетсяоператором вставки,или
помещения, <<. Для операций вывода перегружаетсястандартная операция
сдвига влево <<. Ее левый операнд представляет собой объект типа класса
ostream. Правый операнд может иметь любой тип, для которого определен вывод
потоком (подробнее об этом говорится ниже). Вывод потоком определен для встроенных
типов. Операция<<, перегруженнаядля типа type, называется вставкойэтого
типа. Например,
cout <<
"Hello!\n";
записывает строку "Hello!" в cout
(стандартный поток вывода, который обычно направлен на экран), после чего
следует новая строка. Здесь << - это строка вставки типа char*.
Операция << обладает ассоциативностью слева и возвращает ссылку на
объект ostream, для которого она вызывалась.Это позволяет организовать
каскадные вставки:
void
function_display(int i, double d)
(*
cout <<
"i=" << i << ", d=" << d <<
"\n";
*)
Это вызовет вывод чего-либо
вроде:
i = 8, d = 2.34
на стандартное устройство вывода.
Отметим, что перегрузка не изменяет нормального приоритета выполнения
операции <<, поэтому можно записать:
cout << "sum = "
<< x+y << "\n";
без круглых скобок. Однако, в
случае
cout << (x&y) <<
"\n";
круглые скобки нужны.
Встроенные типы
Типы вставок, поддерживаемые непосредственно,это :
char (signed и unsigned), short (signed иunsigned), int (signed и unsigned),
long (signed и unsigned), char* (рассматриваемый как строка), float, double,
long double и void*. Интегральные типы преобразовываются по правилам, по
умолчанию действующим для printf (еслиэти правила не изменены путем установки
различных флагов ios).Например, если заданы объявления int i; long l;, то
следующие два оператора
cout <<
i << " " << l;
printf("%d %ld, i, l);
приведут к одному и тому же
результату.
Аналогичным образом, типы сплавающей точкой
преобразовываются правилам умолчания для printf с преобразованием %g. Итак, в
случае объявления double d;, операторы
cout <<
d;
printf("%g", d);
дают один и тот же результат.
Вставка
указателя (void*) также предопределена:
int i = 1;
cout << &i; // указатель выводится на
дисплей в шестнадцати// ричном формате
Вставка char работает следующим
образом:
char ch =
'A';
cout << ch; //
на дисплей выводится А
Функции put и write
Для вывода двоичных данных или отдельного символа
можно использовать функцию-компонент put, объявленнуюв ostream следующим
образом:
ostream ostream::put (char ch);
При объявлении int ch='x'; следующие две строки эквивалентны:
cout.put(ch);
cout << (char)ch;
Функция-компонент writeпозволяет вывод больших по
размеру объектов:
ostream& ostream::write(const signed char* ptr, int
n);
ostream&
ostream::write(const unsigned char* ptr, int n);
Функции write выводят nсимволов (включая любые
входящие пустые символы) в двоичномформате. В отличие от строковой вставки,
write не прекращает работу, встретив пустой символ. Например,
cout.write((char *)&x,
sizeof(x))
пошлет непреобразованное представление х
настандартное устройство вывода.
Существует тонкое различие между форматированной операцией
<< и неформатированнымифункциями putи write. Форматированная операция
может вызвать очистку связанных потоков и иметь атрибут ширины
поля.Неформатированные операции не обладают этими свойствами. Поэтому cout
<< 'a' и cout put ('a') могут давать разные результаты. Все флаги
форматирования применимы к <<, но ни один из них не применим к put или
write.
Форматирование вывода
Форматирование ввода и вывода определяется
различными флагами состояний формата, перечисленными в классе ios. Эти
состояния определяются битами числа типа long int следующим образом:
public:
enum (*
skipws =
0x0001, // пропуск пробельного символа на вводе
left =
0x0002, // вывод с левым выравниванием
right = 0x0004, //
вывод с правым выравниванием
internal =
0x0008, // заполнитель после знака или
// указателя
системы счисления
dec =
0x0010, // десятичное преобразование
oct =
0x0020, // восьмеричное преобразование
hex =
0x0040, // шестнадцатиричное преобразование
showbase =
0x0080, // показать на выходе указатель
// системы
счисления
showpoint =
0x0100, // показать позицию десятичной точки
// (на
выходе)
uppercase =
0x0200, // вывод шестнадцатиричных значений
// буквами
верхнего регистра
showpos =
0x0400, // показать знак "+" для положительных
// чисел
scientific =
0x0800, // использовать запись чисел с плава-
// ющей
точкой с выводом экспоненты Е
// например,
12345E2
fixed =
0x1000, // использовать запись чисел с плава-
// ющей
точкой типа 123.45
unitbuf =
0x2000, // стирание всех потоков после вставки
stdio =
0x4000, // стирание stdout и stderr после
// вставки
*);
Разумеется, этифлаги наследуются производными
классами ostream и istream. Приотсутствии специальных действий
пользователяфлагиустанавливаются таким образом, чтобы выполнялось показанное
впримерах выше форматирование по умолчанию. Существуют функции, позволяющие
установке,проверку и сбросфлаговформата, как по отдельности, так и связанными
группами. Некоторые флаги автоматически очищаются после каждого ввода/ вывода.
Основание системы счисления
при преобразованиях
По умолчанию вставкаинтегральных типов выполняется
в десятичной записи. Это можно изменить соответствующими установками флагов
ios::dec, ios::oct и ios::hex (см. раздел "манипуляторы"). Есливсе
эти флаги равнынулю (по умолчанию), то вставка выполняется в десятичном
формате.
Ширина
По умолчанию вставки выводят минимальное число
символов, которыми может бытьпредставлен операнд правой части. Для того, чтобы
изменить это умолчание, можно использовать удобные функции задания ширины
вывода:
int
ios::width(int w); // устанавливает поле ширины в w
// и
возвращает предыдущую ширину
int
ios::width(); // возвращает текущую ширину --
// не внося никаких изменений
Значениеwidth по умолчанию равно нулю, что
эквивалентно выводу без дополнительных заполнителей. Ненулевая ширина означает,
что вставки будут выполнять вывод не уже заданной ширины, ипри
необходимостибудут использованы заполнители до этой ширины. Отметим,
чтоусечение ширины при этом не выполняется: если указанная ширина меньше
фактического числа символовдля представления вывода, то она будет
проигнорирована (как при width, установленной равной нулю). Например,
int i = 123;
int old_w =
cout.width(6);
cout <<
i; // на выводе будет bbb123, где bbb =
// пробелы.
Затем ширина устанавлива-
// ется
равной 0
cout.width(old_w); // восстановление предыдущей
ширины // поля
Отметим, что после каждой форматированной вставки ширина очищается в
ноль, так что в
int i, j;
...
cout.width(4);
cout << i << "
" << j;
i будет представлена минимум четырьмя символами, однако пробел в середине
выражения и j будут представлены минимально необходимым числом символов.
Манипуляторы
Более простой способ изменения состояния ширины и
прочих переменных форматирования состоит в использованииспециальной
функциообразной операции, называемой манипулятором. Манипуляторы принимают в
качестве аргументов ссылку на поток и возвращают ссылку на тот же поток -
поэтому манипуляторы могут объединяться в цепочку вставок (или извлечений из
потока) для того, чтобы изменять состояния потока в виде побочного эффекта,без
фактическоговыполнения каких-либовставок (или извлечений). Например,
cout << setw(4) << i
<< setw(6) << j;
эквивалентно более широкой записи
cout.width(4);
cout <<
i;
cout.width(6);
cout << j;
setw представляет собой параметризованный
манипулятор, объявлениекоторого находится в iomanip.h. Прочие параметризованные
манипуляторы, setbase, setfill, setprecision, setiosflags и resetiosflags,
работают аналогичнымобразом (см таблицу 3.1). Для того, чтобы использовать эти
манипуляторы, ваша программа должна включать iomanip.h. Вы можете писать свои
собственные манипуляторы, без параметров:
ostream&
dingy( ostream os)
(*
return os
<< "\a\a";
*)
...
cout << i << dingy
<< j;
Манипуляторы с параметрами более сложны и требуют включения iomanip.h.
Манипуляторы Таблица
3.1
Манипулятор Синтаксис Действие
dec outs<<dec Установка
флага форма-
ins>>dec тирования
с десятичными
преобразованиями
hex outs<<hex Установка
флага форма-
ins>>hex тирования
с шестнадцати-
ричными преобразованиями
oct outs<<oct Установка
флага форма-
ins>>oct тирования
с восьмеричными
преобразованиями
ws ins>>ws Извлечение
пробельных
символов
endl outs<<endl Вставка
символа новой
строки и очистка потока
ends outs<<ends Вставка
оконечного
пустого символа в строку
flush outs<<flush Очистка
ostream
setbase(int) outs<<setbase(n) Установка
системы счис-
ления при
преобразованиях с основой n (0, 8,
10 или 16). Ноль означает по умолчанию десятичную
систему при выводе и правила С для литералов це-
лых чисел при вводе.
resetiosflags(long) ins>>resetiosflags(l)
Очистка форматных битов outs<<resetiosflags(l) в ins или outs, заданных
аргументом l
setiosflags(long) ins>>setiosflags(l) Установка
форматных битов outs<<setiosflags(l) в ins или outs, заданных аргументом
l
setfill(int)
ins>>setfill(n) Установка символа-за-
полнителяouts<<setfill(n) в n
setprecision(int) ins>>setprecision(n) Установка
точности представления outs<<setprecision(n) чисел с плавающей точкой
равной n разрядам
setw(int) ins>>setw(n) Установка
ширины поля
outs<<setw(n) в
значение n
Не-параметризованные манипуляторы dec, hex и oct
(объявленные в ios.h) непринимают никаких аргументови просто изменяют основание
системы счисления при преобразовании (и оставляютэто изменение в силе):
int i = 36;
cout <<
dec << i << " "
<< hex
<< i << "
<< oct
<< i << endl;
// вывод на дисплей 36 24 44
Манипулятор endl вставляет символ новой строки и
очищает поток. Можно также в любой момент очистить ostream, записав
ostream << flush;
Заполнители и дополнение
вправо и влево
Символ-заполнитель и направление дополнения зависят
от установок внутренних флагов, отвечающих за эти параметры.
По умолчанию
символом-заполнителем является пробел. Изменить данное умолчание позволяет
функция fill:
int i = 123;
cout.fill("*");
cout.width(6);
cout << i; //
на дисплей будет выведено ***123
По умолчанию устанавливается выравнивание по
правому краю (дополнение символами-заполнителями влево). Эти умолчания (а также
прочие форматные флаги) можно изменять при помощи функций setf и unsetf:
int i = 56;
...
cout.width(6);
cout.fill('#');
cout.setf(ios::left,ios::adjustfield);
cout << i //
на дисплей будет выведено 56####
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
|