рефераты

рефераты

 
 
рефераты рефераты

Меню

Реферат: 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