Функция printf() позволяет выводить информацию на экран при программировании в консольном режиме. Данная функция определена в библиотеке stdio.h и имеет следующий синтаксис:
int printf( const char *format [, argument]. );
Здесь первый аргумент *format определяет строку, которая выводится на экран и может содержать специальные управляющие символы для вывода переменных. Затем, следует список необязательных аргументов, которые поясняются ниже. Функуция возвращает либо число отображенных символов, либо отрицательное число в случае своей некорректной работы.
В самой простой реализации функция printf() просто выводит заданную строку на экран монитора:
Однако с ее помощью можно выводить переменные разного типа: начиная с числовых и заканчивая строковыми. Для выполнения этой операции используются специальные управляющие символы, которые называются спецификаторами и которые начинаются с символа %. Следующий пример демонстрирует вывод целочисленной переменной num на экран монитора с помощью функции printf():
int num;
num = 5;
printf(“%d”, num);
В первых двух строках данной программы задается переменная с именем num типа int. В третьей строке выполняется вывод переменной на экран. Работа функции printf() выглядит следующим образом. Сначала функция анализирует строку, которую необходимо вывести на экран. В данном случае это «%d». Если в этой строке встречается спецификатор, то на его место записывается значение переменной, которая является вторым аргументом функции printf(). В результате, вместо исходной строки «%d» на экране появится строка «5», т.е. будет выведено число 5.
Следует отметить, что спецификатор «%d» выводит только целочисленные типы переменных, например int. Для вывода других типов следует использовать другие спецификаторы. Ниже перечислены основные виды спецификаторов:
%с – одиночный символ
%d – десятичное целое число со знаком
%f – число с плавающей точкой (десятичное представление)
%s – строка символов (для строковых переменных)
%u – десятичное целое без знака
%% — печать знака процента
С помощью функции printf() можно выводить сразу несколько переменных. Для этого используется следующая конструкция:
int num_i;
float num_f;
num_i = 5;
num_f = 10.5;
printf(“num_i = %d, num_f = %f”, num_i, num_f);
Результат выполнения программы будет выглядеть так:
num_i = 5, num_f = 10.5
Кроме спецификаторов в функции printf() используются управляющие символы, такие как перевод строки
, табуляции и др. Например, если в ранее рассмотренном примере необходимо вывести значения переменных не в строчку, а в столбик, то необходимо переписать функцию printf() следующим образом:
printf(“num_i = %d,
num_f = %f”, num_i, num_f);
Аналогично используется и символ табуляции.
Для ввода информации с клавиатуры удобно использовать функцию scanf() библиотеки stdio.h, которая имеет следующий синтаксис:
int scanf( const char *format [,argument]. );
Здесь, как и для функции printf(), переменная *format определяет форматную строку для определения типа вводимых данных и может содержать те же спецификаторы что и функция printf(). Затем, следует список необязательных аргументов. Работа функции scanf() демонстрируется на листинге 1.4.
Листинг 1.4. Пример использования функции scanf().
#include
int main()
<
int age;
float weight;
printf(“Введите информацию о Вашем возрасте: ”);
scanf(“%d”, &age);
printf(“Введите информацию о Вашем весе: ”);
scanf(“%f”, &weigth);
printf(“Ваш возраст = %d, Ваш вес = %f”, age, weigth);
Основным отличием применения функции scanf() от функции printf() является знак & перед именем переменной, в которую записываются результаты ввода.
Функция scanf() может работать сразу с несколькими переменными. Предположим, что необходимо ввести два целых числа с клавиатуры. Формально для этого можно дважды вызвать функцию scanf(), однако лучше воспользоваться такой конструкцией:
Функция scanf() интерпретирует это так, как будто ожидает, что пользователь введет число, затем – запятую, а затем – второе число. Все происходит так, как будто требуется ввести два целых числа следующим образом:
Функция scanf() возвращает число успешно считанных элементов. Если операции считывания не происходило, что бывает в том случае, когда вместо ожидаемого цифрового значения вводится какая-либо буква, то возвращаемое значение равно 0.
Очень многие не знают о существовании в языке C стандартных функций форматированного ввода, и особенно вывода данных. Простейший вывод числа в строчку порой превращается в по-настоящему адовые функции с кромсанием числа на разряды (обычно неэффективно реализованным), выделением памяти под строку и прочими ночными кошмарами.
Но всё это реализовано уже очень давно. Страшно сказать, но функция printf празднует в следующем году 50-летний юбилей! Да этих функций и не могло не быть — на заре развития компьютеров и компиляторов единственным средством общения программы с человеком был текстовый ввод-вывод.
Эти функции лежат в библиотеке stdio, подключим её:
Итак, функция которая понадобится вам чаще всего — sprintf. Она принимает:
- указатель на строку, в которую будет помещён результат (char *s)
- строку форматирования, например «напряжение: %d, ток: %d»
- перечень параметров, в этом примере — два целых числа. Здесь используются variable arguments.
sprintf работает как шаблонизатор: она читает строку форматирования, находит в ней идентификаторы, подставляет на их место значения переданных параметров и выводит результат в *s.
В строке форматирования может быть несколько идентификаторов, тогда в качестве параметров должно быть передано такое же количество аргументов, и конечно они должны чётко соответствовать типу, указанному в идентификаторе.
Самые частые случаи
Чаще всего вам понадобятся:
- %d — вывод целого числа: sprintf(s, «масса: %d грамм», 2358) => «масса: 2358 грамм»
- %f — вывод дробного числа: sprintf(s, «пинг: %f секунды», 1.432) => «пинг: 1.432 секунды»
- %s — вывод строки: sprintf(s, «json: <»name»: »%s»>», «joe») => «json: <«name»: «joe»>»
- %02X — вывод байта в виде hex: sprintf(s, «CRC: %02X %02X», 0x43, 0xfe) => «CRC: 43 FE»
Некоторые символы, такие как «, нужно экранировать слешом: »
Можно добавлять управляющие последовательности, например
— перевод строки.
Описание
Каждый идентификатор начинается с символа «%», и сообщает всё о переменной, значение которой нужно подставить: её тип и модификаторы (ширина, точность, размер). Формат идентификатора:
Ни один из элементов не является обязательным, кроме типа. Часть элементов относятся только к некоторым типам, например ширина, точность и размер — только к числовым типам.
Между элементами могут стоять пробелы, но делать так нельзя — резко увеличивается вероятность ошибки.
Числовые целые типы
%d/%i, %u, %o, %x/%X — всё это типы целых чисел int (т.е. оно имеет длину равную разрядности платформы).
%d и %i — десятичное целое знаковое число, минус ставится только у отрицательных чисел.
%u — десятичное целое беззнаковое число.
%o — восьмеричное представление int.
%x — шестнадцатиричное представление int в строчном формате: 0..9, a..f.
%X — шестнадцатиричное представление int в прописном формате: 0..9, A..F.
К ним можно применить модификаторы размера:
%l — число интерпретируется как long int = int16_t
%ll — long long int = int32_t
Флаги:
%0d — вывод ведущих нулей, дополняя число до длины, указанной в поле «ширина»
%-d — выравнивание числа по левому краю
И размерность:
%2d — длина числа минимум 2 символа. Если меньше — оно будет дополнено слева пробелами (либо нулями, если есть флаг 0)
Я очень часто использую идентификатор %02X для вывода шестнадцатиричных чисел в пакетах данных, например:
sprintf(s, «%02X %02X %02X», 0xb3, 0x54, 0xaf) => «B3 54 AF»
Типы с плавающей точкой
%e — экспоненциальная запись
Модификатор размера только один:
К ним можно применить те же самые флаги 0 и -, а также можно указать ширину и точность:
%.2f — выведет float с двумя знаками после запятой. Если они равны 0 — они всё равно будут выведены, поэтому так можно делать красиво выровненные таблички.
%10.2f — как и в прошлой главе, дополнит число нулями или пробелами до длины 10 символов.
Символы
%c выводит символ с кодом, переданным в качестве параметра.
Строки
%s выводит переданную строку, вплоть до её терминирующего нуля.
Особые типы
%n записывает в переданную переменную счётчик символов — количество символов, которое было выведено на момент появления этого идентификатора.
%p выводит адрес указателя.
Варианты функций printf
Мы уже рассмотрели функцию sprintf, как наиболее полезную при программировании под МК — она выводит текст в переданный указатель на строку. Но это не единственная функция из семейства:
- printf(char *format, …) — выводит текст в стандартный вывод (STDIO). Больше применима при программировании для компьютера, но в принципе вы можете переопределить встроенную функцию putc, чтобы она выводила символ как-то по-другому — и сможете, например, выводить через printf напрямую на ЖК-экран.
- snprintf(char *s, int n, char *format, …) — ограничивает количество выведенных символов параметром n, непоместившиеся символы будут потеряны. Очень полезно, если у вас есть какой-то накопительный буфер, который нельзя переполнять.
- fprintf(FILE *f, char *format, …) — выводит текст в файл. Опять же, в основном используется на ПК, но опять же вы можете переопределить её и, например, выводить данные в SD-карту.
- vprintf(char *format, va_list va) — использует перечень аргументов variable arguments. Это просто незаменимая фича при написании своей обёртки вокруг printf.
Все функции вида printf возвращают количество записанных символов.
scanf
Функция, обратная sprintf — это sscanf. Она принимает строку с данными и текстом, пытается её разобрать в соответствии со строкой форматирования, и записывает найденные данные по переданным адресам. Простейший пример:
Здесь действуют все те же самые правила составления идентификаторов, что и в printf, и есть все те же самые функции вроде scanf, fscanf, sscanf.
Основной задачей программирования является обработка информации, поэтому любой язык программирования имеет средства для ввода и вывода информации. В языке Си нет операторов ввода-вывода.
Ввод и вывод информации осуществляется через функции стандартной библиотеки. Прототипы рассматриваемых функций находятся в файле stdio.h . Эта библиотека содержит функции
- printf() — для вывода информации
- scanf() — для ввода информации.
Вывод информации
Функция printf() предназначена для форматированного вывода. Она переводит данные в символьное представление и выводит полученные изображения символов на экран. При этом у программиста имеется возможность форматировать данные, то есть влиять на их представление
на экране.
Общая форма записи функции printf() :
СтрокаФорматов состоит из следующих элементов:
- управляющих символов;
- текста, представленного для непосредственного вывода;
- форматов, предназначенных для вывода значений переменных различных типов.
Объекты могут отсутствовать.
Управляющие символы не выводятся на экран, а управляют расположением выводимых символов. Отличительной чертой управляющего символа является наличие обратного слэша ‘’ перед ним.
Основные управляющие символы:
- ‘
’ — перевод строки; - ‘ ’ — горизонтальная табуляция;
- ‘v’ — вертикальная табуляция;
- ‘’ — возврат на символ;
- ‘
’ — возврат на начало строки; - ‘a’ — звуковой сигнал.
Форматы нужны для того, чтобы указывать вид, в котором информация будет выведена на экран. Отличительной чертой формата является наличие символа процент ‘%’ перед ним:
- %d — целое число типа int со знаком в десятичной системе счисления;
- %u — целое число типа unsigned int ;
- %x — целое число типа int со знаком в шестнадцатеричной системе счисления;
- %o — целое число типа int со знаком в восьмеричной системе счисления;
- %hd — целое число типа short со знаком в десятичной системе счисления;
- %hu — целое число типа unsigned short ;
- %hx — целое число типа short со знаком в шестнадцатеричной системе счисления;
- %ld — целое число типа long int со знаком в десятичной системе счисления;
- %lu — целое число типа unsigned long int ;
- %lx — целое число типа long int со знаком в шестнадцатеричной системе счисления;
- %f — вещественный формат (числа с плавающей точкой типа float );
- %lf — вещественный формат двойной точности (числа с плавающей точкой типа double );
- %e — вещественный формат в экспоненциальной форме (числа с плавающей точкой типа float в экспоненциальной форме);
- %c — символьный формат;
- %s — строковый формат.
Строка форматов содержит форматы для вывода значений. Каждый формат вывода начинается с символа % . После строки форматов через запятую указываются имена переменных, которые необходимо вывести.
Количество символов % в строке формата должно совпадать с количеством переменных для вывода. Тип каждого формата должен совпадать с типом переменной, которая будет выводиться на это место. Замещение форматов вывода значениями переменных происходит в порядке их следования.
Пример на Си
Результат работы программы
Тот же самый код может быть представлен с использованием одного вызова printf :
Табличный вывод
При указании формата можно явным образом указать общее количество знакомест и количество знакомест, занимаемых дробной частью:
В приведенном примере 10 — общее количество знакомест, отводимое под значение переменной; 5 — количество позиций после разделителя целой и дробной части (после десятичной точки). В указанном примере количество знакомест в выводимом числе меньше 10, поэтому свободные знакоместа слева от числа заполняются пробелами. Такой способ форматирования часто используется для построения таблиц.
Ввод информации
Функция форматированного ввода данных с клавиатуры scanf() выполняет чтение данных, вводимых с клавиатуры, преобразует их во внутренний формат и передает вызывающей функции. При этом программист задает правила интерпретации входных данных с помощью спецификаций форматной строки.
Общая форма записи функции scanf( ) :
Строка форматов аналогична функции printf() .
Для формирования адреса переменной используется символ амперсанд ‘&’ :
адрес = &объект
Строка форматов и список аргументов для функции обязательны.
Результат работы программы:
Функция scanf( ) является функцией незащищенного ввода, т.к. появилась она в ранних версиях языка Си. Поэтому чтобы разрешить работу данной функции в современных компиляторах необходимо в начало программы добавить строчку
Другой вариант — воспользоваться функцией защищенного ввода scanf_s( ) , которая появилась несколько позже, но содержит тот же самый список параметров.