Программирование. Принципы и практика использования C++ Исправленное издание, стр. 432

Б.9.5. Обобщенные числовые алгоритмы

 Эти алгоритмы из раздела

<numeric>
обеспечивают общие варианты типичных операций над последовательностями числовых значений.

Программирование. Принципы и практика использования C++ Исправленное издание - _431.png

Б.10. Функции стандартной библиотеки языка С

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

• Ввод-вывод в стиле языка C.

• Строки в стиле языка C.

• Управление памятью.

• Дата и время.

• Остальное.

Библиотека языка С содержит намного больше функций, чем описано в этой книге; рекомендуем читателям обратиться к хорошим учебникам по языку С, например, к книге Kernighan, Ritchie, The C Programming Language (K&R).

Б.10.1. Файлы

Система ввода-вывода, описанная в заголовке

<stdio>
, основана на файлах. Указатель на файл (
FILE*
) может относиться как к файлу, так и к стандартным потокам ввода и вывода,
stdin
,
stdout
и
stderr
. Стандартные потоки доступны по умолчанию; остальные файлы должны быть открыты явным образом.

Программирование. Принципы и практика использования C++ Исправленное издание - _432.png

Режим — это строка, содержащая одну или несколько директив, определяющих, как именно должен быть открыт файл.

Программирование. Принципы и практика использования C++ Исправленное издание - _433.png

В конкретной операционной системе может быть (и, как правило, так и есть) больше возможностей. Некоторые режимы могут комбинироваться, например, инструкция

fopen("foo","rb")
пытается открыть файл
foo
для чтения в бинарном режиме. Режимы ввода-вывода для потоков из библиотек
stdio
и
iostream
должны быть одинаковыми (см. раздел Б.7.1)

Б.10.2. Семейство функций printf()

Наиболее популярными функциями в стандартной библиотеке языка С являются функции ввода-вывода. Тем не менее рекомендуем использовать библиотеку

iostream
, потому что она безопасна с точки зрения типов и допускает расширение. Функция форматированного вывода
printf()
используется очень широко (в том числе и в программах на языке C++) и часто имитируется в других языках программирования.

Программирование. Принципы и практика использования C++ Исправленное издание - _434.png

В каждой версии число

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

Объявление функции

printf()
имеет следующий вид:

int printf(const char* format ...);

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

%c
(вывести символ) и
%d
(вывести целое число). Рассмотрим пример.

int x = 5;

const char* p = "asdf";

printf("Значение x равно '%d', а значение p равно '%s'\n",x,s);

Символ, следующий за знаком

%
управляет обработкой аргументов. Первый знак
%
применяется к первому дополнительному аргументу (в данном примере спецификатор
%d
применяется к переменной
x
), второй знак
%
относится ко второму дополнительному аргументу (в данном примере спецификатор
%s
применяется к переменной
p
) и т.д. В частности, рассмотренный выше вызов функции
printf()
приводит к следующему результату:

Значение x равно '5', а значение p равно 'asdf'

Затем происходит переход на новую строку.

В принципе соответствие между директивой преобразования

%
и типом, к которому она применяется, проверить невозможно. Рассмотрим пример.

printf("Значение x равно '%s', а значение p равно '%d'\n",x,p); // ой!

Набор спецификаторов преобразования довольно велик и обеспечивает большую гибкость (а также много возможностей сделать ошибку). За символом

%
могут следовать спецификаторы, описанные ниже.

Программирование. Принципы и практика использования C++ Исправленное издание - _435.png

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

Поскольку в языке C нет пользовательских типов в смысле языка C++, в нем нет возможностей для определения форматов вывода для таких классов, как

complex
,
vector
или
string
.

Стандартный поток вывода

stdout
в языке C соответствует потоку
cout
. Стандартный поток ввода
stdin
в языке С соответствует потоку
cin
. Стандартный поток сообщений об ошибках
stderr
в языке С соответствует потоку
cerr
. Эти соответствия между стандартными потоками ввода-вывода в языке C и C++ настолько близки, что потоки ввода-вывода как в стиле языка С, так и стиле языка С++ могут использовать один и тот ж буфер. Например, для создания одного и того же потока вывода можно использовать комбинацию операций над объектами
cout
и
stdout
(такая ситуация часто встречается в смешанном коде, написанном на языка С и С++). Эта гибкость требует затрат. Для того чтобы получить более высокую производительность, не смешивайте операции с потоками из библиотек
stdio
и
iostream
при работе с одним и тем же потоком, вместо этого вызывайте функцию
ios_base::sync_with_stdio(false)
перед выполнением первой операции ввода-вывода. В библиотеке
stdio
определена функция
scanf()
, т.е. операция ввода, похожая на функцию
printf()
. Рассмотрим пример.