Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Паппас К., Мюррей У. - Visual C++ 6. Руководство разработчика - 2000

.pdf
Скачиваний:
288
Добавлен:
13.08.2013
Размер:
4.96 Mб
Скачать

pfi = fopen("integer.dat", "wb"); if(pfi == NULL) { printf("Heудалось открыть файл."); exit(l); } while(Ifeof(pfi)) { ivalue = getw(pfi); printf("%3d",ivalue); } }

Посмотрите, какие данные будут выведены на экран при выполнении этой программы, и попытайтесь определить, что было сделано неправильно:

1 2 3 4 5 6 7 8 9 10 -1

Поскольку в цикле while может встретиться признак конца файла EOF, в программе используется функция feof() , сигнализирующая об обнаружении конца файла. Но особенностью этой функции является то, что она не выполняет упреждающего чтения, а лишь проверяет состояние специального флага, который, в свою очередь, устанавливается только после того, как будет непосредственно выполнена операция чтения признака конца файла.

Чтобы исправить ошибку, допущенную в предыдущем примере, применим метод упреждающего чтения.

/*

*getwputw.c

*Это исправленная версия предыдущего примера .

*/

#include <stdio.h> #include <stdlib.h> #define ISIZE 10 void main () { FILE *pfi;

int ivalue, ivalues [ISIZE], 1;

pfi = f open ("integer .dat","wb"); if (pfi == NULL) { printf("Heудалось открыть файл.");

exit(l); } ford = 0; i < ISIZE; 1++) { ivalues [i]= i + 1,-

putw (ivalues [i], pfi); ) f close (pfi); pfi = fopen ("integer .dat","rb");

if (pfi== NULL) ( printf("Heудалось открыть файл."); exit(l);

}

ivalue = getw(pfi); while(Ifeof(pfi)) { printf("%3d",ivalue) ivalue = getw(pfi); }

Прежде чем приступить к выполнению цикла while, программа осуществляет упреждающее чтение файла, для того чтобы проверить, не является ли он пустым. Если файл не пуст, то в переменную ivalue будет записано целочисленное значение. Если же файл окажется пустым, то это будет обнаружено функцией feof( ) .

Также обратите внимание, что метод упреждающего чтения потребовал изменения последовательности инструкций в цикле while. Предположим, цикл выполнен уже девять раз. На девятой итерации переменная ivalueприняла значение 9. На следующей итерации на экран будет выведено 9, а переменной будет присвоено значение 10. Цикл выполнится еще раз, в результате чего на экране отобразится 10 и переменная ivalueпримет значение -1, соответствующее константе EOF. Это вызовет завершение цикла while, поскольку функция feof(} определит конец файла.

Форматный вывод данных

Для вывода форматированных данных, как правило, применяются функции printf() и fprintf(). Первая записывает данные в поток stdout, а вторая — в указанный файл или поток. Как уже говорилось ранее, аргументами функции printf() являются строка форматирования и список выводимых переменных. (В функции fprintf() первый аргумент — указатель файла.) Для каждой

191

переменной из списка задание формата вывода осуществляется с помощью следующего синтаксиса:

%[флаги][ширина][.точность][{h | 1}]спецификатор

В простейшем случае указывается только знак процента и спецификатор, например %f.Обязательное поле спецификатор указывает на способ интерпретации переменной: как символа, строки или числа (табл. 10.2). Необязательное поле флаги определяет дополнительные особенности вывода (табл. 10.3).

Необязательное поле ширина задает минимальную ширину поля вывода. Если количество выводимых символов меньше указанного значения, поле дополняется слева или справа пробелами или нулями в зависимости от установленных флагов.

Необязательное поле точность интерпретируется следующим образом:

при выводе чисел формата е, Е и fопределяет количество цифр после десятичной точки (последняя цифра округляется);

при выводе чисел формата gи G определяет количество значащих цифр (по умолчанию 6);

при выводе целых чисел определяет минимальное количество цифр (если цифр недостаточно, число дополняется ведущими нулями);

при выводе строк определяет максимальное количество символов, лишние символы отбрасываются (по умолчанию строка выводится, пока не встретится символ \о).

Поля ширина и точность могут быть заданы с помощью символа-заменителя *. В этом случае в списке переменных должны быть указаны их настоящие значения.

Необязательные модификаторы hи 1 определяют размерность целочисленной переменной: hсоответствует ключевому слову short, al — long.

Таблица 10.2. Спецификаторы типа переменной в функциях printf() и fprintf()

Спецификатор

Тип

Формат вывода

 

 

 

 

 

 

c

int

Символ (переменная приводится к типу unsignedchar)

 

 

 

d, i

int

Знаковое десятичное целое число

 

 

 

o

int

Беззнаковое восьмеричное целое число

 

 

 

u

int

Беззнаковое десятичное целое число

 

 

 

x

int

Беззнаковое шестнадцатеричное целое число (в качестве цифр от 10 до 15 используются

 

 

буквы "abcdef')

 

 

 

X

int

Беззнаковое шестнадцатеричное целое число (в качестве цифр от 10 до 15 используются

 

 

буквы "ABCDEF")

 

 

 

e

double

Знаковое число с плавающей запятой в формате [ - ] т. ddde xxx, где т — одна десятичная

 

 

цифра, ddd— ноль или более десятичных цифр (количество определяется значением поля

 

 

точность, нулевая точность подавляет вывод десятичной точки, по умолчанию точность —

 

 

6), 'е' — символ экспоненты, ххх — ровно три десятичные цифры (показатель экспоненты)

 

 

 

E

double

То же, что и е, только вместо символа 'е' применяется 'Е'

f

double Знаковое число с плавающей запятой в формате [ - ] mmm.ddd, где mmm — одна или более десятичных цифр, ddd — ноль или более десятичных цифр (количество определяется значением поля точность, нулевая точность подавляет вывод десятичной точки, по умолчанию точность — 6)

g

double Знаковое число с плавающей запятой в формате f или е; формат е выбирается, если показатель экспоненты меньше -4 или больше либо равен значению поля точность; десятичная точка не ставится, если за ней не следуют значащие цифры; хвостовые нули не выводятся

G

double

То же, что и g, но при необходимости выбирается формат Е, а не е

 

 

 

n

int *

Ничего не выводится; количество символов, выведенных к данному моменту функцией,

 

 

записывается в переменную

 

 

 

192

 

 

 

p

void *

Адрес, содержащийся в указателе (отображается в формате х)

 

 

 

s

char *

Строка символов; вывод осуществляется до тех пор, пока не будет обнаружен символ \0 или

 

 

число символов не станет равным значению поля точность

 

 

 

Таблица 10.3. Флаги в фугкциях printf() и fprintf()

Флаг Назначение

-Если число выведенных символов оказывается меньше указанного, результат выравнивается по левому краю поля вывода (по умолчанию принято правостороннее выравнивание)

+При выводе знаковых чисел знак отображается всегда (по умолчанию знак устанавливается только перед отрицательными числами)

Если значению поля ширина предшествует символ '0', выводимое число дополняется ведущими нулями до

0минимальной ширины поля вывода (по умолчанию в качестве заполнителей применяются пробелы); при левостороннем выравнивании игнорируется

пробел Если выводится положительное знаковое число, перед ним ставится пробел (по умолчанию пробел в таких случаях не ставится); игнорируется при наличии флага +

Для чисел формата о, х и X означает добавление ведущих 0, 0х и 0Х соответственно (по умолчанию

#отсутствуют); для чисел формата е, Е, g, G и f задает присутствие десятичной точки, даже когда за ней не следуют значащие цифры (по умолчанию точка в таких случаях не ставится); для чисел формата g и G предотвращает отбрасывание хвостовых нулей (по умолчанию отбрасываются)

Функция printf()

В следующей программе демонстрируется, как правильно применять различные спецификаторы форматирования к переменным четырех типов: символу, массиву символов, целому числу и числу с плавающей запятой. Программа содержит достаточно подробные комментарии, а, кроме того, выводимые строки пронумерованы, чтобы легче было обнаружить, какая из функций их сгенерировала.

/*

*printf.c

*Эта программа на языке С демонстрирует применение

*спецификаторов форматирования функции printfO.

*/

#include <stdio.h> void main () {

char

с

= 'А',

 

psz[]= "Строка для экспериментов";

 

int

iln = 0,

 

ivalue = 1234;

 

double dPi

= 3.14159265;

 

/* 1

— вывод

символа с */

 

printf("\n[%2d] %c",++iln, c) ;

 

/* 2

— вывод

ASCII-кода символа с */

 

printf<"\n[%2d] %d",++iln, c);

 

/* 3

— вывод

символа с ASCII-кодом 90 */

 

printf("\n[%2d] %c",++iln, 90);

 

/* 4

— вывод

значения ivalue в восьмеричной системе */

printf("\n[%2d] %o",++iln, ivalue);

 

/* 5

— вывод

значения ivalue в шестнадцатеричной */

/* системе с

буквами в нижнем регистре */

 

printf("\n[%2d]%х",++iln, ivalue);

 

/* 6

— вывод

значения ivalue в шестнадцатеричной */

/*

системе с буквами в верхнем регистре

*/

printf("\n[%2d]%Х",++iln, ivalue);

 

/* 7

— вывод

одного символа, минимальная ширина поля равна 5, */

/* выравнивание вправо с дополнением пробелами

*/

printf("\n[%2d]%5c",++iln, с); .

 

193

/* 8 -- вывод одного символа, минимальная ширина поля равна 5, */

/* выравнивание влево с дополнением пробелами

*/

printf("\n[%2d]%-5c",++iln, с);

 

/* 9 — вывод строки, отображаются 24 символа */

 

printf("\n[%2d]%s",++iln, psz);

 

/* 10 — вывод минимум 5-ти символов строки, отображаются 24 символа */ printf ("\n[%d]%5s",-n-iln, psz);

/* 11 — вывод минимум 38-ми символов строки, */ /* выравнивание вправо с дополнением пробелами */ printf("\n[%d]%38s",++iln, psz);

/*12 — вывод минимум 38-ми символов строки, */ /* выравнивание влево с дополнением пробелами */ printf("\n[%d]%-38s",++iln, psz);

/* 13 — вывод значения ivalue, по умолчанию отображаются 4 цифры */ printf("\n[%d]%d",++iln, ivalue);

/* 14 — вывод значения ivalueсо знаком */ printf("\n[%d]%+d",++iln, ivalue);

/* 15 — вывод значения ivalueминимум из 3-х цифр, */ /* отображаются 4 цифры*/

printf("\n[%d]%3d",++iln, ivalue);

/* 16 — вывод значения ivalueминимум из 10-ти цифр, */ /* выравнивание вправо с дополнением пробелами */ printf("\n[%d]%10d",++iln, ivalue);

/* 17 — вывод значения ivalueминимум из 10-ти цифр, '*/

/*

выравнивание влево с дополнением пробелами

*/

printf("\n[%d]%-10d",++iln, ivalue);

 

 

/* 18 — вывод значения

ivalue минимум из 10-ти

цифр, */

/*

выравнивание вправо с дополнением нулями

*/

printf ("\n[%d]%010d",-n-iln, ivalue);

 

 

/* 19 — вывод значения

dPiс форматированием по

умолчанию */

printf("\n[%d]%f",++iln, dPi); .

 

 

/* 20 — вывод значения

dPi, минимальная ширина

поля равна 20, */

/* выравнивание вправо

с дополнением пробелами

*/

 

printf("\n[%d]%20f",++iln, dPi) ;

 

 

/* 21 — вывод значения

dPi, минимальная ширина

поля равна 20, */

/*'выравнивание вправо

с дополнением нулями

 

*/

printf("\n[%d]%020f",++iln, dPi) ;

/* 22 — вывод значения dPi, минимальная ширина поля равна 20, */

/* выравнивание влево с дополнением пробелами

*/

printf("\n[%d]%-20f",++iln, dPi);

 

 

 

/* 23 — вывод 19-ти символов строки,

*/

 

/*

минимальная ширина поля равна 19 */

 

printf("\n[%d]%19.19s",++iln, psz);

строки */

 

/* 24 — вывод первых двух

символов

 

printf("\n[%d]%,2s",++iln, psz);

 

 

 

/*'25 — вывод первых двух

символов

строки, минимальная ширина поля */

/* равна 19, выравнивание

вправо с

дополнением пробелами '*/

printf("\n[%d]119.2s",++iln, psz);

 

 

 

/* 26 — вывод первых двух

символов

строки, минимальная ширина поля */

/* равна 19, выравнивание

влево с дополнением пробелами */

printf("\n[%d]%-19.2s",++iln, psz);

/* 27 "- вывод первых шести символов строки, минимальная ширина поля

*/ /* равна 19, выравнивание вправо с дополнением пробелами */

194

printf ("\n[%d]%*.*s",++iln, 19,6, psz);

/* 28 — вывод значения dPi,минимальная ширина поля */

/*

равна

10, 8 цифр после десятичной точки

*/

printf("\n[%d]

%10.8f",++iln, dPi);

 

/* 29 — вывод значения dPi, минимальная ширина поля */ /* равна 20, 2 цифры после десятичной точки, */ /* выравнивание вправо с дополнением пробелами */ printf("\n[%d]%20.2f",++iln, dPi) ;

/*' 30 — вывод, значения dPi, минимальная ширина поля */

.

/*

равна 20, 4 цифры после десятичной точки,

*/

/*

. выравнивание влево с

дополнением пробелами */

printf("\n[%d]%-20.4f",++iln,

dPi);

 

/* 31 — вывод значения dPi, минимальная ширина поля */ /* равна 20, 4 цифры после десятичной точки, */ /* выравнивание вправо с дополнением пробелами */ printf("\n[%d]%20.4f",++iln, dPi);

/* 32 — вывод значения dPi, минимальная ширина поля */ /* равна 20, 2 цифры после десятичной точки, */ /* выравнивание вправо с дополнением пробелами, */

/* научный формат (с экспонентой)

*/

printf("\n[%d]%20.2e",++iln, dPi);

 

Результат работы программы будет выглядеть следующим образом:

[ 1] А

 

[ 2] 65

 

[ 3] Z

 

[ 4] 2322

 

[ 5] 4d2

 

[ 6] 4D2

 

[ 7]

А

[ 8] А [ 9] Строка для экспериментов

[10]Строка для экспериментов

[11]Строка для экспериментов [12]Строка для экспериментов

[13]1234

.

[14]

+1234

 

[15]1234

 

[16]

1234

 

[17]1234

 

[18]

0000001234

 

[19]3.141593

 

[20]

3.141593

[21]0000000000003.141593

 

[22]

3.141593

 

[23]Строка для эксперим

 

[24]Ст

[25]Ст

[26]Ст

[27]Строка

[28]3.14159265

[29]

3.14

[30]3.1416

 

195

[31]

3.1416

[32]3.14е+000

Поиск в файлах с помощью функций fseek( ), ftell( ) и rewind()

Функции fseek(),ftell() и rewind() предназначены для определения и изменения положения маркера текущей позиции файла. Первая из них, fseek() , перемещает маркер в файле, заданном указателем pf, на требуемое число байтов, определенное аргументом ibytes.

Перемещение осуществляется от начала файла (аргумент ifrom равен 0), от текущего положения маркера (аргумент ifrom равен 1) или от конца файла (аргумент ifrom равен 2). В языке С предусмотрены три константы, которые можно указывать в качестве аргумента ifrom: seek_set (сдвиг от начала файла), seek_cur(сдвиг от текущей позиции) и seek_end(сдвиг от конца файла). Функция fseek ( ) возвращает ноль при успешном завершении и EOF в противном случае. Синтаксис функции таков:

fseek(pf, ibytes, ifrom) ;

Функция ftell() возвращает текущую позицию маркера в файле, которая определяется величиной смещения в байтах от начала файла. Возвращаемое значение имеет тип long.

Функция rewind( ) просто перемещает маркер в начало файла.

В следующей программе на языке С продемонстрировано использование всех трех функций: fseek(),ftell() и rewind().

/*

*fseek.с

*Эта программа на языке С демонстрирует использование

*функций fseek(), ftell() и rewind() .

*/

#include <stdio.h>

void

main ( ) {

FILE

*pf;

char

c;

long

llocation;

pf =

fopen("test.dat","r+t");

с= fgetc(pf ) ; putchar (c) ;

с= fgetc(pf ) ; putchar (c);

llocation = ftell (pf ) ;

с= fgetc (pf) ;

putchar (c); fseek(pf,llocation, 0) ;

с= fgetc(pf) ; putchar(с);

fseek(pf, llocation, 0); fputc.(E1, pf) ; fseek(pf,llooation, 0) ;

с= fgetc(pf); putchar(c); rewind (pf);

с= fgetc (pf) ; putchar(c);

}

Переменная llocation имеет тип long. Это связано с тем, что язык С поддерживает работу с файлами, размер которых превышает 64 Кб. Файл TEST.DAT содержит строку "ABCD". Первая из функций fgetc() возвращает букву 'А', после чего программа выводит ее на экран. В следующих двух строках выводится буква 'В'.

196

Далее функция ftell() записывает в переменную llocation значение маркера текущей позиции в файле. Поскольку буква 'В' уже прочитана, переменная llocationбудет содержать 2. Это означает, что в данный момент маркер указывает на третий символ, который смещен на 2 байта от первого символа 'А'.

Вследующей паре строк считывается и отображается буква 'С'. После выполнения данной операции маркер сдвинется на четвертый символ — 'D'.

Вэтом месте программа вызывает функцию fseek (), которая перемещает маркер на 2 байта от начала файла (отсчет идет от начала файла, поскольку третий аргумент функции равен 0). После выполнения функции маркер вновь "указывает на третий символ в файле. Поэтому в результате работы следующих двух строк на экран будет выведена буква 'С'.

При втором вызове функции fseek() устанавливаются те же параметры, что и в первом случае. Но на этот раз с помощью функции fputc() в файл записывается буква 'Е' на место буквы 'С'. Чтобы убедиться, что новая буква действительно была вставлена в файл, программа в очередной раз обращается к функции fseek()для перемещения к третьей позиции, считывает символ в этой позиции и отображает его. Этим символом будет 'Е'.

3атем вызывается функция rewind(),которая перемещает маркер в начало файла. При следующем вызове функции fgetc() из файла считывается буква 'А', которая и выводится на экран. В результате работы программы на экране будет получена следующая последовательность букв:

АВССЕА

Форматный ввод

Форматирование вводимых данных в языке С можно осуществлять с помощью достаточно мощных функций scanf() и fscanf (), Различие между ними заключается в том, что последняя требует указания файла, из которого читаются данные. Функция scanf() принимает данные из стандартного входного потока stdin.

Функции scanfC ), fscanf( ) и sscanf( )

Функция scanf (), как и ее "родственники" fscanf() и sscanf (), в качестве аргумента принимает такого же рода строку форматирования, что и функция printf(), осуществляющая вывод данных, хотя имеются и некоторые отличия. Для примера рассмотрим следующее выражение:

scanf("%2d%5s%4f", sivalue, psz, &fvalue);

Данная функция считывает целое число, состоящее из двух цифр, строку из пяти символов и число с плавающей запятой, образованное не более чем четырьмя символами (2,97, 12,5 и т.п.). Все аргументы, перечисленные после строки форматирования, должны быть указателями, т.е. содержать адреса переменных. А теперь попробуем разобрать более сложное выражение:

scanf (" \"%[^А-Zа-z-] %*[-] %[^\"]",

ps1, ps2);

Первым в строке форматирования стоит пробел. Он служит указанием пропустить все ведущие пробелы, символы табуляции и новой строки, пока не встретится двойная кавычка (")В строке форматирования этот символ защищен обратной косой чертой (\"), так как в противном случае он означал бы завершение самой строки! Таким образом, обратная косая черта является своего рода командой отмены специального назначения следующего за ней символа.

Управляющая последовательность %[^A-Za-z-] говоритотом, что встроку рs1 нужно вводить все, кроме букв и символа дефиса (-). Квадратные скобки, в которых на первом месте стоит знак крышки (Л), определяют диапазон символов, из которых не должна состоять вводимая строка. В данном случае в диапазон входят буквы от 'А' до 'Z' (дефис между ними означает "от и до") и от 'а' до 'z', а также сам дефис. Если убрать знак ^, то, наоборот, будут ожидаться только буквы и символы дефиса. В конец прочитанной строки добавляется символ \0. Если во входном потоке вслед за открывающей кавычкой первыми встретятся буква или дефис, выполнение функции scanf() завершится ошибкой и в переменные ps1 и рs2 ничего не будет записано, а сама строка останется в буфере потока. Чтение строки ps1 продолжается до тех пор, пока не встретится один из символов, указанных после знака ^.

Вторая управляющая последовательность % * [ - ] говорит о том, что после чтения строки ps1 должна быть обнаружена группа из одного или нескольких дефисов, которые необходимо

197

пропустить. Символ звездочки (*) указывает на то, что данные должны быть прочитаны, но не сохранены. Отметим два важных момента.

Если после строки ps1 первой встретится буква, а не дефис, выполнение функции scanf() завершится ошибкой, в переменную ps2 ничего не будет записано, а сама строка останется в буфере потока.

Если бы в первой управляющей последовательности символ дефиса не был отмечен как пропускаемый, функция scanf() работала бы неправильно, так как символ дефиса, являющийся "ограничителем" строки ps1, воспринимался бы как часть этой строки! В этом случае чтение было бы прекращено только после обнаружения буквы, а это, в свою очередь, привело бы к возникновению ошибки, описанной в первом пункте.

Последняя управляющая последовательность %[^\"] указывает на то, что в строку ps2 нужно считывать все символы, кроме двойных кавычек, которые являются признаком завершения ввода.

Для полной ясности приведем пример входной строки:

"65---ААА"

Вот что будет получено в результате: *psl= 65, *ps2 = ааа.

Все вышесказанное справедливо и в отношении функций fscanf () и sscanf (). Функция sscanf() работает точно так же, как и scanf(),но читает данные из указанного символьного массива, а не из потока stdin. В следующем примере показано, как с помощью функции sscanf()

преобразовать строку цифр в целое число: sscanf(psz,"%d",&ivalue);

198

Глава 11. Основы ввода-вывода в языке C++

Подсистема ввода-вывода в C++

o Стандартные потоки cin , cout и сеrr

oОператоры ввода (>>) и вывода (<<) данных

Флаги и функции форматирования

Файловый ввод-вывод

Определение состояния потока

Хотя в целом C++ является расширенной версией языка С, это не означает, что для создания эффективной программы достаточно взять каждое выражение на С и записать его синтаксический эквивалент на C++. Очень часто C++ предлагает не только дополнительные операторы, но и новые способы решения традиционных задач. Одним из новшеств языка является уникальная подсистема ввода-вывода, знакомство с которой мы начнем в этой главе, а завершим в главе 15. Разделение данной темы на две главы необходимо из-за разнообразия средств ввода-вывода, используемых в C++, что связано с внедрением в язык концепции объектно-ориентированного прoграммирования. Только после того, как вы уясните принципы создания объектов и манипулирования ими, вы сможете в полной мере освоить новую методику ввода-вывода данных посредством объектов. Пока же вам следует быть готовыми к тому, что некоторые термины и понятия, упоминаемые в настоящей главе, могут оказаться для вас незнакомыми.

Подсистема ввода-вывода в C++

Стандартные функции ввода-вывода, используемые в языке С и объявленные в файле STDIO.H, доступны также и в C++. В то же время C++ располагает своим собственным файлом заголовков IOSTREAM.H, содержащим набор средств ввода-вывода, специфичных для этого языка.

Потоковый ввод-вывод в C++ организуется посредством комплекта стандартных классов, подключаемых с помощью файла IOSTREAM.H. Эти классы содержат перегруженные операторы ввода >> и вывода <<, которые поддерживают работу с данными всевозможных типов. Чтобы лучше понять, почему легче работать с потоками в C++, чём в С, давайте вспомним, как вообще в языке С реализуется ввод и вывод данных.

Прежде всего вспомним о том, что язык С не имеет встроенных средств ввода-вывода. Все функции, такие как printf() или scanf(), предоставляются через внешние библиотеки, хоть и считающиеся стандартными, но не являющиеся частью самого языка. В принципе, это позволяет гибко решать проблемы, возникающие в различных приложениях, в соответствии с их особенностями и назначением.

Трудности появляются в связи с тем, что подобного рода функций слишком много, они поразному возвращают значения и принимают разные аргументы. Программисты полагаются главным образом на функции форматного ввода-вывода, printf(), scanf() и им подобные, особенно если приходится работать с числами, а не текстом. Эти функции достаточно универсальны, но зачастую, из-за обилия всевозможных спецификаторов форматирования, становятся чересчур громоздкими и трудно читаемыми.

Язык C++ точно так же не располагает встроенными средствами ввода-вывода, но предлагает модульный подход к решению данной проблемы, группируя возможности ввода-вывода в трех основных потоковых классах:

istream содержит средства ввода ostream содержит средства вывода

iostream поддерживает двунаправленный ввод-вывод, является производным от первых двух классов

Во всех этих классах реализованы операторы << и >>, оптимизированные для работы с конкретными данными.

199

Библиотека IOSTREAM.H содержит также классы, с помощью которых можно управлять вводом-выводом данных из файлов:

ifstream Порожден от istreamи подключает к программе файл, предназначенный для ввода данных

ofstream Порожден от ostream и подключает к программе файл, предназначенный для вывода данных

fstream Порожден от iostream и подключает к программе файл, предназначенный как для ввода, так и для вывода данных

Стандартные потоки cin, coutи cerr

Стандартным потокам языка С stdin, stdoutи stderr, объявленным в файле STDIO.H, в C++ соответствуют объекты-потоки cin, cout, cerrи clog, подключаемые посредством файла

IOSTREAM.H.

cin Объект класса istream, связанный со стандартным потоком ввода cout Объект класса ostream, связанный со стандартным потоком вывода

cerr Объект класса ostream, не поддерживающий буферизацию и связанный со стандартным потоком ошибок

clog Объект класса ostream, поддерживающий буферизацию и связанный со стандартным потоком ошибок

Все они открываются автоматически во время запуска программы и обеспечивают интерфейс между программой и пользователем.

Операторы ввода (>>) и вывода (<<) данных

Ввод-вывод в C++ значительно усовершенствован и упрощен благодаря универсальным операторам >> (ввод) и << (вывод). Их универсальность стала возможной благодаря появившемуся в C++ понятию перегрузки операторов, которая заключается в создании функций, имена которых совпадают с именами стандартных операторов языка. Компилятор различает вызов настоящего и "функционального" операторов на основании типов передаваемых им операндов. Операторы >> и << перегружены таким образом, чтобы поддерживать все стандартные типы данных C++, включая классы. Рассмотрим пример вывода данных с помощью функции printf() в языке С:

printf("Целое числей.'/%d,, число с плавающей запятой: %f",ivalue, fvalue);

А теперь запишем это же выражение на C++:

cout<< "Целое число: " << ivalue<< ", число с плавающей запятой: " << fvalue;

Обратите внимание, что один и тот же перегруженный оператор используется для вывода данных трех разных типов: строк, целых чисел и чисел с плавающей запятой. Оператор << самостоятельно проанализирует тип данных и выберет подходящий формат их представления. Аналогично работает оператор ввода. Сравним два эквивалентных выражения на языках С и C++:

/* на языке С */ scanf("%d%f%c",&ivalue, &fvalue, &c); // на языке С+.+

cin >> ivalue >> fvalue >> c;

Нет необходимости при вводе данных ставить перед именами переменных оператор взятия адреса &. В C++ оператор >> берет на себя задачу вычисления адреса, определения формата и прочих особенностей записи значения переменной.

Прямым следствием перегрузки является возможность расширения операторов << и>> для обработки данных нестандартных типов. Ниже показано, как перегрузить оператор вывода, чтобы он мог принимать данные нового типа tclient:

ostream&

operator <<(ostream& osout, tclient client)

{

 

osout<< " " << client.pszname; osout<< " " << client.pszaddress;

200

Соседние файлы в предмете Программирование на C++