2.2 Организация ввода/вывода
Потоковый ввод/вывод
Один из основных механизмов, который делает программу полезной является
ввод/вывод. Все языки программирования имеют такой механизм. Среди операторов
и ключевых слов нет ввода/вывода. Потому что в языке С++ ввод/вывод реализован
в виде библиотеки. И вообще многие механизмы, которые делают язык С++
таким мощным реализованы в библиотеках (стандартные, специализированные,
персональные).
В С++ используется механизм потокового ввода/вывода. Поток - механизм
преобразования значений различного типа в последовательность символов
(вывод) и наоборот (ввод), в значение переменной.
Вывод: Помещение (направление) данных в поток вывода осуществляется
с помощью оператора << который также иногда называют экстрактор
(extractor). Конечно, можно создать свой поток вывода, но обычно достаточно
стандартных потоков:
- cout - стандартный поток вывода (экран)
- cerr - стандартный поток вывода ошибок (экран)
Переменную любого встроенного типа можно вывести используя следующую
запись:
cout<<"x="<<x; // переменная x будет преобразована
в набор символов
Можно определить операторы потокового ввода/вывода и для созданных абстрактных
типов данных.
Ввод: Ввод данных из потока осуществляется аналогично с использованием
обратного оператора >> (inserter):
- cin - стандартный поток ввода (клавиатура)
Переменную любого временного типа можно ввести (считать) из потока:
cin>>x;
Для использования стандартной библиотеки нужно включить ее описание
в текст программы. Это делается с помощью директивы препроцессору #include.
#include <iostream> // подключение стандартной библиотеки
using namespace std; // объявление об использовании стандартного пространства
имен
void main() // функция main
{
cout<<"Data types:"<<endl; // вывод
строки
cout<<"int = "<<sizeof(int)<<endl;
// вывод строки и целочисленного значения
cout<<"float = "<<sizeof(float)<<endl;
cout<<"double = "<<sizeof(double)<<endl;
}
Форматированный ввод/вывод
В С++ используется механизм потокового ввода/вывода. Поток - механизм
преобразования значений различного типа в последовательность символов
(вывод) и наоборот (ввод)
#include <iostream>
Примеры, которые приводились выше и ввод/вывод, который вы использовали
на практических занятиях до сих пор, обычно называют неформатированным
выводом.
Часто программисту нужно более детализированное управление. Управление
осуществляется для каждого потока отдельно, т.е. если вы определили какой-то
формат для потока ввода, то на поток вывода он не подействует. Более того,
управление влияет только на следующее выводимое значение.
#include <iomanip>
Управление можно организовать используя манипуляторы потока, которые
вставляются между объектами (записываемыми или читаемыми) и тем самым
изменяют состояние потока (формат вывода значений):
для вывода целых чисел
dec; // устанавливает десятичную систему счисления
hex; // устанавливает шестнадцатеричную систему счисления
oct; // устанавливает восьмеричную систему счисления
setbase(int b); // вывод целых чисел в системе счисления с основанием
b(10,8...)
show base; // показывает основание системы счисления
для вывода чисел с плавающей точкой
- по умолчанию используется универсальный формат, который наилучшим
образом представляет число с точностью 6 значащих цифр:
float f=1234.56789;
cout<<f; // 1234.57
- научный формат, который представляет число десятичной дробью с одной
цифрой перед точкой с показателем степени
cout<<scientific<<f; // 1.2345678e+03
- фиксированный формат представляет число как целую часть с дробной
частью отделенной точкой. Точность определяет максимальное число цифр
после точки. Точность устанавливается с помощью манипулятора setpresision(int
n) n - цифр после точки
cout<<fixed<<f; // 1234.567890
для вывода логических переменных
bool valuet=true;
bool valuef=false;
cout<<valuet<<valuef; // 1 0
cout<<boolalpha<< valuet<<valuef; // true false
Дополнительно можно определить ширину вывода переменных в количестве
символов:
setw(int n); // если строка или число длиннее, то будут выведены
все setw(0)
А также задать символ для заполнения
setfill(int c);
cout<<setw(4)<<setfill(#)<<12; // ##12
Можно определить место размещения заполнителей. По умолчанию как видите
заполнители размещаются до значения. Это аналогично записи:
cout<<setw(4)<<setfill('#')<<right<<12;
Можно наоборот:
cout<<setw(4)<<setfill('#')<<left<<12;
// 12##
Важные манипуляторы:
endl; // заканчивается строка, т.е. вставляется символ '\n'
ends; // заканчивается строка записью '
'
flush; // очистка буфера потока
Это лишь основные манипуляторы, которые вы можете использовать для форматирования.
С остальными познакомьтесь самостоятельно:
Манипулятор |
Действие на поток |
showbase
noshowbase |
инициирует отображение основания системы счисления |
showpos
noshowpos |
инициирует явное отображение знака (+) для положительных значений |
uppercase
nouppercase |
инициирует преобразование выводимых символов в верхний регистр |
showpoint
noshowpoint |
инициирует отображение десятичной точки при выводе вещественных
чисел |
skipws
noskipws |
инициирует пропуск пробельных символов при вводе |
left |
инициирует левое выравнивание, заполнение справа |
right |
инициирует правое выравнивание, заполнение слева |
internal |
инициирует внутреннее заполнение (между значением и знаком или
основанием системы счисления) |
scientific |
инициирует вывод вещественных значений в научном формате (d.ddddddddE+dd) |
fixed |
инициирует вывод вещественных значений в фиксированном формате
(d.dddddd) |
setbase (int base) |
изменяет систему счисления (10, 8, 16) |
dec |
инициирует вывод целочисленных значений в десятичной системе счисления |
oct |
инициирует вывод целочисленных значений в восьмеричной системе
счисления |
hex |
инициирует вывод целочисленных значений в шестнадцатеричной системе
счисления |
setfill (char n) |
задает заполняющий символ |
setprecision (int n) |
изменяет точность выводимых значений |
setw (int n) |
задает ширину поля вывода |
Файловые потоки
Для первых программ стандартных потоков ввода/вывода будет достаточно,
но по мере усложнения программ не обойтись без работы с файлом, которая
в С++ осуществляется так же на основе механизма потоков.
#include <fstream>
using namespace std;
void main()
{
ifstream inputfile("z:\data.txt"); // создается
поток ввода из файла
inputfile>>x; // все то же самое что и
для cin
ofstream outputfile("z:\res.txt"); // создается
поток вывода в файл
outputfile<<x; // все то же самое что
и для cout
}
Обратите внимание на двойной слэш \ в имени файла. Это все из-за того,
что \ - экранирующий символ.
По умолчанию ввод и вывод данных в поток осуществляется в текстовом
режиме. Для того, чтобы данные выводились в двоичном режиме следует использовать
следующую запись:
ofstream outfile(filename,ios::binary);
По умолчанию файл открываемый для вывода создается (если он создан),
а если существует, то очищается. Для того чтобы открыть файл для добавления:
ofstream outfile(filename,ios::app);
Можно создать файловый поток, который запускает и ввод и вывод:
fstream iofile(filename,ios::in|ios::out);
|