Вернуться наверх
aco.ifmo.ru photonic
вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


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);