1.6. Ввод-вывод

Форматный вывод данных осуществляется функцией printf : int printf ( строка формата [ , список вывода ] ) которая возвращает количество выведенных символов. Список вывода может содержать любые выражения, разделенные запятыми (полностью аналогичен списку вывода оператора WRITE в языке PASCAL). Строка формата заключается в " " и может содержать :

1) обычные символы, которые просто выводятся на экран;

2) специальные символы, управляющие размещением данных на экране;

3) элементы формата данных.

Для вывода строки на экран элементы формата можно не использовать, в этом случае список вывода пуст :

рпведем что-нибудь...\а");

Элемент формата представляет собой последовательность :

% [ - ] [ длина поля ] [ . точность ] [ 1 ] спецификация типа " - " означает сдвиг выводимых данных к левому краю поля ( по умолчанию дан­ные сдвигаются вправо); длина поля - количество позиций для вывода; точ­ность - количество дробных цифр для чисел или количество выводимых симво­лов строки для строк; " . " - разделитель; 1 - означает, что число должно рассмат­риваться как long или double. Могут использоваться следующие спецификации типов :

d,i - для данных типа int;

u - для данных типа unsigned;

o  - для данных типа unsigned (выводятся в восьмеричном виде);

x,X - для данных типа unsigned (выводятся в шестнадцатеричном виде), ше-стнадцатеричные цифры A,B,C,D,E,F изображаются большими буквами при ис­пользовании типа X и малыми буквами при использовании x;

c  - для данных типа char, unsigned char (выводятся в символьном виде);

f - для данных типа float,double (выводятся в виде с фиксированной точкой, по умолчанию выводится 6 дробных цифр);

e, E - для данных типа float,double (выводятся в виде с плавающей точкой, по умолчанию выводится 7 цифр мантиссы и две цифры порядка, всего 13 позиций), отличаются изображением буквы E;

g,G - для данных типа float,double - величины 0.0001<|x|<1000000 выводятся в виде с фиксированной точкой с шестью значащими цифрами, другие величины выводятся с плавающей точкой с шестью значащими цифрами (всего занимают 12 позиций), спецификации g и G различаются только изображением буквы e(E);

s - для строк;

p  - для данных типа указатель.

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

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

d,u - для ввода целых десятичных чисел;

0 - для ввода восьмеричных чисел (можно со знаком);

x,X - для ввода шестнадцатеричных чисел (можно со знаком);

1 - для ввода целых чисел, которые могут задаваться любой целой константой языка С (т.е. восьмеричные константы начинаются с 0, а шестнадцатеричные - с 0x);

c - для ввода символов;

f, e,E,g,G - для ввода вещественных чисел, которые могут изображаться лю­бой десятичной константой с фиксированной или плавающей точкой.

Модификаторы " - ", длина поля и точность при вводе игнорируются. Вве­денное значение затем преобразуется к типу вводимой переменной. Для данных типа int и unsigned можно использовать спецификации d,u,o,x,X,i, но для пере­менных типа 1ong обязательно следует указать модификатор 1, т.е. использовать спецификации ld,lu и т.д. Данные типа char и unsigned char можно вводить по формату с. Спецификации f,e,E,g,G применимы для ввода переменных типа float, для переменных типа doub1e добавляется модификатор 1. Вводимые числа разде­ляются любым количеством пробелов. Символы считываются подряд, если перед каким-либо из элементов формата %с не стоит пробел; в противном случае про­белы считаются разделителями. Строка формата может содержать перед первым % некоторую последовательность символов, тогда вводимая строка данныхдолжна начинаться этой последовательностью, которая пропускается функцией scanf и лишь со следующего символа начинается ввод данных. Функция scanf осуществляет ввод до обнаружения первого недопустимого символа во входном потоке и возвращает количество успешно введенных значений (аварийного пре­рывания при обнаружении неверных входных данных не происходит). Однако функция никак не контролирует соответствие типа вводимых переменных и ис­пользуемых элементов формата.

Для ввода-вывода символов используются функции getchar и putchar. Функция int getchar() возвращает введенный символ, преобразованный к типу int. Функция int putchar(int c) выводит в символьном виде значение c и возвра­щает выведенное значение. Прототипы функций scanf, printf, getchar и putchar находятся в файле stdio.h . Недостатком функции getchar является необходи­мость после набора символа нажимать клавишу Enter. В большинстве случаев вместо нее удобно пользоваться функциями, прототипы которых находятся в conio.h : int getch() и int getche() . Эти функции возвращают значение, соответ­ствующее нажатой клавише (аналогичны функции ReadKey в языке PASCAL). При этом getche высвечивает на экране введенный символ, а getch - нет. С по­мощью этих функций можно опрашивать и клавиши, генерирующие два кода, -стрелки, функциональные клавиши и т.п.

Язык С++ полностью поддерживает средства ввода-вывода языка С. Вместе с тем в С++ введен новый способ ввода-вывода, который носит название ввода-вывода потоком. Поток определяется как некоторый абстрактный тип данных, представляющий последовательность элементов данных, направленную от ис­точника (source) к потребителю (consumer). Количество элементов в потоке на­зывается его длиной, порядковый номер доступного в некоторый момент эле­мента называют текущей позицией (current position). Используемые в програм­мах потоки логически делятся на три типа:

1) входные, из которых читается информация;

2) выходные, в которые передаются данные;

3) двунаправленные, допускающие как чтение, так и запись.

В начале выполнения программы автоматически открываются четыре пото­ка: cin, cout, cerr и clog, описанные в файле iostream.h . Поток cin связан со стандартным вводом (по умолчанию с клавиатурой), cout - со стандартным вы­водом (по умолчанию с дисплеем). Вместо записи: #inc1ude <stdio.h>

printf("Вывод = %d,%f\n",i,r); scanf("%d",&x); на С++ можно записать:

#inc1ude <iostream.h>

cout«"Вывод="«i«","«r«end1; cin>>e1ement;

Выполнение операции >> (извлечение из потока) заключается в преобразо­вании последовательности символов потока в значение типизированного объек­та. При выполнении операции << (включение в поток) совершается обратное преобразование - типизированное значение выражения преобразуется в последо­вательность символов потока. Отметим, что операции << и >> распознаются какоперации потокового ввода-вывода, если они употребляются справа от имен по­токовых объектов

cin >> имя_ объекта базового типа

cout << выражение базового типа

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

cout << (x+y<z);

Операции сдвига также можно использовать в выводимых выражениях, но обязательно должны быть использованы скобки. Оператор cout<<(2<<1); выве­дет в поток значение 4. В библиотеке потокового ввода-вывода С++ предусмот­рена возможность форматирования передаваемых данных, для этого применяют­ся два способа. Первый состоит в использовании флагов форматирования, кото­рые унаследованы всеми потоками библиотеки из базового класса ios. При вто­ром способе форматирования употребляется специальный вид функций, назы­ваемых манипуляторами.