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

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 нет пользовательских типов в смысле языка 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. Рассмотрим пример.

int x;

char s[buf_size];

int i = scanf("Значение x равно '%d', а значение s равно '%s'\n",&x,s);

Здесь функция scanf пытается считать целое число в переменную x и последовательность символов, не являющихся разделителями, в массив s. Неформатные символы указывают, что они должны содержаться в строке ввода. Рассмотрим пример.

"Значение x равно '123', а значение s равно 'string '\n"

Программа введет число 123 в переменную x и строку "string", за которой следует 0, в массив s. Если вызов функции scanf завершает работу успешно, результирующее значение (i в предыдущем вызове) будет равно количеству присвоенных аргументов-указателей (в данном примере это число равно 2); в противном случае оно равно EOF. Этот способ индикации ввода уязвим для ошибок (например, что произойдет, если вы забудете вставить пробел после строки "string" в строке ввода?). Все аргументы функции scanf должны быть указателями. Мы настоятельно рекомендуем не использовать эту функцию.

Как же ввести данные, если мы вынуждены использовать библиотеку stdio? Один и из распространенных ответов гласит: “Используйте стандартную библиотечную функцию gets”.

// очень опасный код:

char s[buf_size];

char* p = gets(s); // считывает строку в массив s

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT