Вывод данных в языке C++

Для вывода данных в языке C++ предназначены объекты cout, cerr и clog, объявленные в файле iostream. Объект cout (console output — вывод на консоль) используется для вывода обычных сообщений в окно консоли. Объекты cerr и clog применяются для вывода сообщений об ошибках. Также как и объект cout объекты cerr и clog первоначально связаны с окном консоли, однако возможно перенаправить поток на другое устройство или в файл. Для понимания всех возможностей этих объектов требуется знание принципов объектно-ориентированного программирования (ООП). Так как ООП мы еще не изучали, в этом разделе будут рассматриваться только основные возможности объектов. В последующих главах мы вернемся к изучению этих объектов.

Прежде чем использовать объекты, необходимо подключить файл iostream с помощью директивы #include:

#include <iostream>

Обратите внимание на то, что название файла указывается внутри угловых скобок без расширения, так как файл iostream входит в состав стандартной библиотеки C++. После подключения файла все объекты будут доступны через пространство имен std, поэтому при обращении к объекту необходимо указать название пространства имен и два символа двоеточия перед названием объекта. Например, вывести строку "Hello, world!" можно так:

std::cout << "Hello, world!";

Вывести сообщение об ошибке можно так (на вкладке Вывод приложения редактора QtCreator такие сообщения отображаются красным цветом):

std::cerr << "Error 1";
std::clog << "Error 2";

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

using namespace std;

В этом случае название пространства имен указывать не нужно:

cout << "Hello, world!";

Хотя это очень удобно, следует избегать импортирования всех идентификаторов в глобальное пространство имен, так как возможен конфликт имен. Вместо этого способа лучше импортировать определенные идентификаторы. Например, импортировать только объект cout можно так:

using std::cout;

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

std::cout << 10;                // Целое число
std::cout << 81.5;              // Вещественное число
std::cout << "Hello, world!";   // Строка
char str[] = "Hello, world!";
std::cout << str;               // Строка

Результат выполнения этого примера будет таким:

1081.5Hello, world!Hello, world!

Как видно из результата, все данные выводятся на одной строке. Чтобы данные выводились на отдельных строках можно воспользоваться константой endl (сокращение от «end line»). Пример:

std::cout << "String1";
std::cout << std::endl;
std::cout << "String2";

Результат в окне консоли:

String1
String2

На самом деле endl не совсем константа. Можно сказать, что это функция (называемая манипулятором), внутри которой производится вывод символа перевода строки, сбрасывается буфер, а затем возвращается ссылка на поток вывода. Благодаря возврату ссылки можно строить цепочки из операторов <<. Например, предыдущий пример можно записать так:

std::cout << "String1" << std::endl << "String2";

Для перевода строки можно также воспользоваться комбинацией символов \n, которая обозначает символ перевода строки. Пример:

std::cout << "String1" << '\n' << "String2";

Для вывода строк, состоящих из двухбайтовых символов, предназначены объекты wcout, wcerr и wclog, объявленные в файле iostream. Объект wcout предназначен для вывода обычных сообщений, а объекты wcerr и wclog для вывода сообщений об ошибках (для вывода сообщений на русском языке следует предварительно настроить локаль):

// #include <clocale>
std::setlocale(LC_ALL, "Russian_Russia.1251"); // Настройка локали
std::wcout << L"String";
std::wcerr << L"Error 1";
std::wclog << L"Error 2";

С помощью стандартного вывода можно создать индикатор выполнения процесса в окне консоли. Чтобы реализовать такой индикатор нужно вспомнить, что символ перевода строки в Windows состоит из двух символов \r (перевод каретки) и \n (перевод строки). Таким образом, используя только символ перевода каретки \r можно перемещаться в начало строки и перезаписывать ранее выведенную информацию. Пример индикатора процесса показан в листинге 2.5.

Листинг 2.5. Индикатор выполнения процесса

#include <iostream>
#include <windows.h>

int main() {
   std::cout << "... 0%";
   for (int i = 5; i < 101; i += 5) {
      Sleep(1000); // Имитация процесса
      std::cout << "\r... " << i << "%";
      std::cout.flush();
   }
   std::cout << std::endl;
   return 0;
}

Открываем командную строку (в редакторе QtCreator эффекта не будет видно), компилируем программу и запускаем:

C:\book>g++ -Wall -Wconversion -O3 -o helloworld.exe helloworld.cpp

C:\book>helloworld.exe

Эта программа немного сложнее, чем простое приветствие из листинга 2.1. Здесь присутствует имитация процесса с помощью функции Sleep() (при этом программа «засыпает» на указанное количество миллисекунд). Прототип функции:

#include <windows.h>
VOID Sleep(DWORD dwMilliseconds);

Тип данных DWORD объявлен так:

typedef unsigned __LONG32 DWORD;
#define __LONG32 long

Кроме того, в программе использован цикл for, который позволяет изменить порядок обработки инструкций. Обычно программа выполняется сверху вниз и слева направо. Инструкция за инструкцией. Цикл for меняет эту последовательность выполнения. Инструкции, расположенные внутри блока, выполняются несколько раз. Количество повторений зависит от выражений внутри круглых скобок. Этих выражений три, и разделены они точками с запятой. Первое выражение объявляет целочисленную переменную i и присваивает ей значение 5. Второе выражение является условием продолжения повторений. Пока значение переменной i меньше значения 101, инструкции внутри блока будут повторяться. Это условие проверяется на каждой итерации цикла. Третье выражение на каждой итерации цикла прибавляет значение 5 к текущему значению переменной i.

Так как данные перед выводом могут помещаться в буфер, вполне возможно потребуется сбросить буфер явным образом. Сделать это можно с помощью метода flush():

std::cout.flush();

Или с помощью функции fflush(). Прототип функции:

#include <cstdio> /* или #include <stdio.h> */
int fflush(FILE *stream)

В качестве параметра указывается стандартный поток вывода stdout:

std::fflush(stdout);

Вывод данных в языке C

Язык C++ поддерживает также операции вывода из языка C, объявленные в файле stdio.h. В языке C++ вместо этого файла можно подключать файл cstdio:

#include <cstdio>

Для вывода одиночного символа применяется функция putchar(). Прототип функции:

#include <cstdio> /* или #include <stdio.h> */
int putchar(int ch);

Пример вывода символа:

std::putchar('w'); // w
std::putchar(119); // w

Вывести строку позволяет функция puts(). Прототип функции:

#include <cstdio> /* или #include <stdio.h> */
int puts(const char *str);

Функция выводит строку str и вставляет символ перевода строки. Пример:

std::puts("String1");
std::puts("String2");

Результат выполнения:

String1
String2

Для форматированного вывода используется функция printf(). Можно также воспользоваться функцией _printf_l(), которая позволяет дополнительно задать локаль. Прототипы функций:

#include <cstdio> /* или #include <stdio.h> */
int printf(const char *format, ...);
int _printf_l(const char *format, _locale_t locale, ...);

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

std::printf("String\n");
std::printf("Count %d\n", 10);
std::printf("%s %d\n", "Count", 10);

Результат выполнения:

String
Count 10
Count 10

В первом примере строка формата не содержит спецификаторов и выводится как есть. Во втором примере внутри строки формата используется спецификатор %d, предназначенный для вывода целого числа. Вместо этого спецификатора подставляется число 10, переданное во втором параметре. В третьем примере строка содержит сразу два спецификатора %s и %d. Спецификатор %s, предназначен для вывода строки, а спецификатор %d — для вывода целого числа. Вместо спецификатора %s будет подставлена строка Count, а вместо спецификатора %d — число 10. Обратите внимание на то, что тип данных переданных значений должен совпадать с типом спецификатора. Если в качестве значения для спецификатора %s указать число, то это приведет в ошибке времени исполнения. На этапе компиляции будет выведено лишь предупреждающее сообщение:

warning: format '%s' expects argument of type 'char*', but argument 2
has type 'int' [-Wformat=]

Параметр locale в функции _printf_l() позволяет задать локаль. Настройки локали для разных стран отличаются. Например, в одной стране принято десятичный разделитель вещественных чисел выводить в виде точки, в другой — в виде запятой. В функции printf() используются настройки локали по умолчанию. Пример:

// #include <clocale>
_locale_t locale = _create_locale(LC_NUMERIC, "dutch");
std::printf("%.2f\n", 2.5);            // 2.50
_printf_l("%.2f\n", locale, 2.5);      // 2,50
std::setlocale(LC_NUMERIC, "dutch");
std::printf("%.2f\n", 2.5);            // 2,50
_free_locale(locale);

Спецификаторы имеют следующий синтаксис:

%[<Флаги>][<Ширина>][.<Точность>][<Размер>]<Тип>

В параметре <Тип> могут быть указаны следующие символы:

  • c — символ:
std::printf("%c", 'w'); // w
std::printf("%c", 119); // w
  • s — строка:
std::printf("%s", "String"); // String
  • d или i — десятичное целое число со знаком:
std::printf("%d %i", 10, 30);   // 10 30
std::printf("%d %i", -10, -30); // -10 -30
  • u — десятичное целое число без знака:
std::printf("%u", 10); // 10
  • o — восьмеричное число без знака:
std::printf("%o %o", 10, 077);   // 12 77
std::printf("%#o %#o", 10, 077); // 012 077
  • x — шестнадцатеричное число без знака в нижнем регистре:
std::printf("%x %x", 10, 0xff);   // a ff
std::printf("%#x %#x", 10, 0xff); // 0xa 0xff
  • X — шестнадцатеричное число без знака в верхнем регистре:
std::printf("%X %X", 10, 0xff);   // A FF
std::printf("%#X %#X", 10, 0xff); // 0XA 0XFF
  • f — вещественное число в десятичном представлении:
std::printf("%f %f", 18.65781452, 12.5); // 18.657815 12.500000
std::printf("%f", -18.65781452);         // -18.657815
std::printf("%#.0f %.0f", 100.0, 100.0); // 100. 100
  • e — вещественное число в экспоненциальной форме (буква «e» в нижнем регистре):
std::printf("%e", 18657.81452); // 1.865781e+04
std::printf("%e", 0.000081452); // 8.145200e-05
  • E — вещественное число в экспоненциальной форме (буква «e» в верхнем регистре):
std::printf("%E", 18657.81452); // 1.865781E+04
  • g — эквивалентно f или e (выбирается более короткая запись числа):
std::printf("%g %g %g", 0.086578, 0.000086578, 1.865E-005);
// 0.086578 8.6578e-05 1.865e-05
  • G — эквивалентно f или E (выбирается более короткая запись числа):
std::printf("%G %G %G", 0.086578, 0.000086578, 1.865E-005);
// 0.086578 8.6578E-05 1.865E-05
  • p — вывод адреса переменной:
int x = 10;
std::printf("%p", &x);
// 000000000023fe4c
  • % — символ процента (%):
std::printf("10%%"); // 10%

Параметр <Ширина> задает минимальную ширину поля. Если строка меньше ширины поля, то она дополняется пробелами. Если строка не помещается в указанную ширину, то значение игнорируется и строка выводится полностью:

std::printf("'%3s'", "string");  // 'string'
std::printf("'%10s'", "string"); // '    string'

Задать минимальную ширину можно не только для строк, но и для других типов:

std::printf("'%10d'", 25);   // '        25'
std::printf("'%10f'", 12.5); // ' 12.500000'

Параметр <Точность> задает количество знаков после точки для вещественных чисел. Перед этим параметром обязательно должна стоять точка. Пример:

std::printf("'%10.5f'", 3.14159265359); // '   3.14159'
std::printf("'%.3f'", 3.14159265359);   // '3.142'

Если параметр <Точность> используется применительно к целому числу, то он задает минимальное количество цифр. Если число содержит меньшее количество цифр, то вначале числа добавляются нули. Пример:

std::printf("'%7d'", 100);        // '    100'
std::printf("'%.7d'", 100);       // '0000100'
std::printf("'%.7d'", 123456789); // '123456789'

Если параметр <Точность> используется применительно к строке, то он задает максимальное количество символов. Символы, которые не помещаются, будут отброшены. Пример:

std::printf("'%5.7s'", "Hello, world!");   // 'Hello, '
std::printf("'%15.20s'", "Hello, world!"); // '  Hello, world!'

Вместо минимальной ширины и точности можно указать символ *. В этом случае значения передаются через параметры функции printf() в порядке указания символов в строке формата. Примеры:

std::printf("'%*.*f'", 10, 5, 3.14159265359); // '   3.14159'
std::printf("'%.*f'", 3, 3.14159265359);      // '3.142'
std::printf("'%*s'", 10, "string");           // '    string'

В первом примере вместо первого символа * подставляется число 10, указанное во втором параметре, а вместо второго символа * подставляется число 5, указанное в третьем параметре. Во втором примере вместо символа * подставляется число 3, которое задает количество цифр после точки. В третьем примере символ * заменяется числом 10, которое задает минимальную ширину поля.

В параметре <Флаги> могут быть указаны следующие символы:

  • # — для восьмеричных значений добавляет в начало символ 0, для шестнадцатеричных значений добавляет комбинацию символов 0x (если используется тип x) или 0X (если используется тип X), для вещественных чисел указывает всегда выводить дробную точку, даже если задано значение 0 в параметре <Точность>:
std::printf("%#o %#o", 10, 077);         // 012 077
std::printf("%#x %#x", 10, 0xff);        // 0xa 0xff
std::printf("%#X %#X", 10, 0xff);        // 0XA 0XFF
std::printf("%#.0f %.0f", 100.0, 100.0); // 100. 100
  • 0 — задает наличие ведущих нулей для числового значения:
std::printf("'%7d'", 100);  // '    100'
std::printf("'%07d'", 100); // '0000100'
  • - — задает выравнивание по левой границе области. По умолчанию используется выравнивание по правой границе. Пример:
std::printf("'%5d' '%-5d'", 3, 3);   // '    3' '3    '
  • пробел — вставляет пробел перед положительным числом. Перед отрицательным числом будет стоять минус. Пример:
std::printf("'% d' '% d'", -3, 3); // '-3' ' 3'
  • + — задает обязательный вывод знака, как для отрицательных, так и для положительных чисел. Пример:
std::printf("'%+d' '%+d'", -3, 3); // '-3' '+3'

В параметре <Размер> могут быть указаны следующие буквы:

  • h — для вывода значения переменной, имеющей тип short int. Пример:
short int x = 32767;
std::printf("%hd", x); // 32767
unsigned short int y = 65535;
std::printf("%hu", y); // 65535

При передаче в функцию значение типа short автоматически расширяется до типа int, поэтому букву h можно вообще не указывать:

short x = 32767;
std::printf("%d", x);  // 32767
unsigned short y = 65535;
std::printf("%u", y);  // 65535
  • l (буква «эль») — для вывода значения переменной, имеющей тип long int. Пример:
long int x = 2147483647L;
std::printf("%ld", x); // 2147483647

Модификатор l можно использовать совместно с типами c и s, для вывода двухбайтового символа и строки, состоящей из двухбайтовых символов, соответственно. Пример:

wchar_t str[] = L"string";
std::printf("%ls", str); // string
  • ll — для вывода значения переменной, имеющей тип long long. Пример:
long long x = 9223372036854775807LL;
std::printf("%lld\n", x); // 9223372036854775807
  • L — для вывода значения переменной, имеющей тип long double. Пример:
long double x = 8e+245;
std::printf("%Le", x); // 8.000000e+245

Если выводить несколько значений подряд с помощью функции printf(), то они все отобразятся на одной строке:

std::printf("string1");
std::printf("string2");
// string1string2

Чтобы значения выводились на отдельных строках нужно воспользоваться комбинацией символов \n, обозначающей перевод строки:

std::printf("string1\n");
std::printf("string2");
/*
string1
string2 */

Следует учитывать, что функции putchar(), puts() и printf() применяются в языке C. Хотя их можно использовать и в языке C++, тем не менее для вывода данных стоит отдать предпочтение объекту cout. Описание функций putchar(), puts() и printf() приведено в этой книге лишь для того, чтобы вы могли разобраться в чужом коде.

Учебник C++ (Qt Creator и MinGW)
Учебник C++ (Qt Creator и MinGW) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов