Функции стандартного ввода/вывода (printf, scanf)
Стандартная библиотека C/C++ включает ряд функций для чтения и записи на консоли (клавиатура и монитор). Эти функции читают и пишут данные как простой поток символов.
Понятие потока (stream), использованное в программировании, тесно связано с обычным, бытовым пониманием этого слова. Поток ввода можно сравнить с трубой, по которой вода (информация) поступает в бассейн (память компьютера), поток вывода — с трубой, по которой вода выходит из бассейна. Важной особенностью этой трубы является то, что в каждый момент времени данные могут двигаться только в одном направлении. Даже если одна и та же труба используется для ввода и вывода, это не может происходить одновременно: для переключения направления потока его нужно остановить, выполнить некие действия и лишь затем направить поток в обратном направлении. Другой особенностью потока является то, что он почти никогда не иссякает. Иногда он высыхает, но этот период не может быть долгим, если система функционирует нормально.
Функция стандартного вывода printf()
Функция printf() является функцией стандартного вывода. С помощью этой функции можно вывести на экран монитора строку символов, число, значение переменной.
Функция printf() имеет прототип в файле stdio.h
int printf(char *управляющая строка, . );
В случае успеха функция printf() возвращает число выведенных символов.
Управляющая строка содержит два типа информации: символы, которые непосредственно выводятся на экран, и спецификаторы формата, определяющие, как выводить аргументы.
Функция printf() это функция форматированного вывода. Это означает, что в параметрах функции необходимо указать формат данных, которые будут выводиться. Формат данных указывается спецификаторами формата. Спецификатор формата начинается с символа % за которым следует код формата.
| %с | символ |
| %d | целое десятичное число |
| %i | целое десятичное число |
| %e | десятичное число в виде x.xx e+xx |
| %E | десятичное число в виде x.xx E+xx |
| %f | десятичное число с плавающей запятой xx.xxxx |
| %F | десятичное число с плавающей запятой xx.xxxx |
| %g | %f или %e, что короче |
| %G | %F или %E, что короче |
| %o | восьмеричное число |
| %s | строка символов |
| %u | беззнаковое десятичное число |
| %x | шестнадцатеричное число |
| %X | шестнадцатеричное число |
| %% | символ % |
| %p | указатель |
| %n | указатель |
Кроме того, к командам формата могут быть применены модификаторы l и h.
| %ld | печать long int |
| %hu | печать short unsigned |
| %Lf | печать long double |
В спецификаторе формата, после символа % может быть указана точность (число цифр после запятой). Точность задаётся следующим образом: %.n. Где n — число цифр после запятой, а — один из кодов приведённых выше.
Например, если у нас есть переменная x=10.3563 типа float и мы хотим вывести её значение с точностью до 3-х цифр после запятой, то мы должны написать:
printf(«Переменная x = %.3f»,x);
Результат:
Переменная x = 10.356
Вы также можете указать минимальную ширину поля отводимого для печати. Если строка или число больше указанной ширины поля, то строка или число печатается полностью.
Например, если вы напишите:
то результат будет следующим:
20
Обратите внимание на то, что число 20 напечаталось не с самого начала строки. Если вы хотите чтобы неиспользованные места поля заполнялись нулями, то нужно поставить перед шириной поля символ 0.
Кроме спецификаторов формата данных в управляющей строке могут находиться управляющие символы:
| \b | BS, забой |
| \f | Новая страница, перевод страницы |
| \n | Новая строка, перевод строки |
| \r | Возврат каретки |
| \t | Горизонтальная табуляция |
| \v | Вертикальная табуляция |
| \» | Двойная кавычка |
| \’ | Апостроф |
| \ | Обратная косая черта |
| Нулевой символ, нулевой байт | |
| \a | Сигнал |
| \N | Восьмеричная константа |
| \xN | Шестнадцатеричная константа |
| \? | Знак вопроса |
Чаще всего вы будете использовать символ \n. С помощью этого управляющего символа вы сможете переходить на новую строку. Посмотрите примеры программ и вы всё поймёте.
/* Пример 1 */
#include
void main(void)
int a,b,c; // Объявление переменных a,b,c
a=5;
b=6;
c=9;
printf(«a=%d, b=%d, c=%d»,a,b,c);
>
Результат работы программы:
a=5, b=6, c=9
/* Пример 2 */
#include
void main(void)
float x,y,z;
printf(«Координаты объекта: x:%.2f, y:%.2f, z:%.2f», x, y, z);
>
Результат работы программы:
Координаты объекта: x:10.50, y:130.67, z:54.00
/* Пример 3 */
#include
Результат работы программы:
x=10
/* Пример 4 */
#include
void main(void)
printf(«\»Текст в кавычках\»»);
printf(«\nСодержание кислорода: 100%%»);
>
Результат работы программы:
«Текст в кавычках»
Содержание кислорода: 100%
/* Пример 5 */
#include
void main(void)
int a;
a=11; // 11 в десятичной равно b в шестнадцатеричной
printf(«a-dec=%d, a-hex=%X»,a,a);
>
Результат работы программы:
a-dec=11, a-hex=b
/* Пример 6 */
#include
void main(void)
char ch1,ch2,ch3;
Результат работы программы:
ABC
/* Пример 7 */
#include
void main(void)
char *str=»Моя строка.»;
Результат работы программы:
Это Моя строка.
/* Пример 8 */
#include
void main(void)
printf(«Здравствуйте!\n»); // После печати будет переход на новую строку — \n
printf(«Меня зовут Павел.»); // Это будет напечатано на новой строке
>
Результат работы программы:
Здравствуйте!
Меня зовут Павел.
Функция стандартного ввода scanf()
Функция scanf() — функция форматированного ввода. С её помощью вы можете вводить данные со стандартного устройства ввода (клавиатуры). Вводимыми данными могут быть целые числа, числа с плавающей запятой, символы, строки и указатели.
Функция scanf() имеет следующий прототип в файле stdio.h:
int scanf(char *управляющая строка);
Функция возвращает число переменных которым было присвоено значение.
Управляющая строка содержит три вида символов: спецификаторы формата, пробелы и другие символы. Спецификаторы формата начинаются с символа %.
| %c | чтение символа |
| %d | чтение десятичного целого |
| %i | чтение десятичного целого |
| %e | чтение числа типа float (плавающая запятая) |
| %h | чтение short int |
| %o | чтение восьмеричного числа |
| %s | чтение строки |
| %x | чтение шестнадцатеричного числа |
| %p | чтение указателя |
| %n | чтение указателя в увеличенном формате |
При вводе строки с помощью функции scanf() (спецификатор формата %s), строка вводиться до первого пробела!! т.е. если вы вводите строку «Привет мир!» с использованием функции scanf()
char str[80]; // массив на 80 символов
scanf(«%s»,str);
то после ввода результирующая строка, которая будет храниться в массиве str будет состоять из одного слова «Привет». ФУНКЦИЯ ВВОДИТ СТРОКУ ДО ПЕРВОГО ПРОБЕЛА! Если вы хотите вводить строки с пробелами, то используйте функцию
char *gets( char *buf );
С помощью функции gets() вы сможете вводить полноценные строки. Функция gets() читает символы с клавиатуры до появления символа новой строки (\n). Сам символ новой строки появляется, когда вы нажимаете клавишу enter. Функция возвращает указатель на buf. buf — буфер (память) для вводимой строки.
Хотя gets() не входит в тему этой статьи, но всё же давайте напишем пример программы, которая позволяет ввести целую строку с клавиатуры и вывести её на экран.
void main(void)
char buffer[100]; // массив (буфер) для вводимой строки
gets(buffer); // вводим строку и нажимаем enter
printf(«%s»,buffer); // вывод введённой строки на экран
>
Ещё одно важное замечание! Для ввода данных с помощью функции scanf(), ей в качестве параметров нужно передавать адреса переменных, а не сами переменные. Чтобы получить адрес переменной, нужно поставить перед именем переменной знак &(амперсанд). Знак & означает взятие адреса.
Что значит адрес? Попробую объяснить. В программе у нас есть переменная. Переменная хранит своё значение в памяти компьютера. Так вот адрес, который мы получаем с помощью & это адрес в памяти компьютера где храниться значение переменной.
Давайте рассмотрим пример программы, который показывает нам как использовать &
void main(void)
int x;
printf(«Введите переменную x:»);
scanf(«%d»,&x);
printf(«Переменная x=%d»,x);
>
Теперь давайте вернёмся к управляющей строке функции scanf(). Ещё раз:
int scanf(char *управляющая строка);
Символ пробела в управляющей строке дает команду пропустить один или более пробелов в потоке ввода. Кроме пробела может восприниматься символ табуляции или новой строки. Ненулевой символ указывает на чтение и отбрасывание этого символа.
Разделителями между двумя вводимыми числами являются символы пробела, табуляции или новой строки. Знак * после % и перед кодом формата (спецификатором формата) дает команду прочитать данные указанного типа, но не присваивать это значение.
при вводе 50+20 присвоит переменной i значение 50, переменной j — значение 20, а символ + будет прочитан и проигнорирован.
В команде формата может быть указана наибольшая ширина поля, которая подлежит считыванию.
указывает необходимость прочитать из потока ввода первые 5 символов. При вводе 1234567890ABC массив str будет содержать только 12345, остальные символы будут проигнорированы. Разделители: пробел, символ табуляции и символ новой строки — при вводе символа воспринимаются, как и все другие символы.
Если в управляющей строке встречаются какие-либо другие символы, то они предназначаются для того, чтобы определить и пропустить соответствующий символ. Поток символов 10plus20 оператором
присвоит переменной x значение 10, переменной y — значение 20, а символы plus пропустит, так как они встретились в управляющей строке.
Одной из мощных особенностей функции scanf() является возможность задания множества поиска (scanset). Множество поиска определяет набор символов, с которыми будут сравниваться читаемые функцией scanf() символы. Функция scanf() читает символы до тех пор, пока они встречаются в множестве поиска. Как только символ, который введен, не встретился в множестве поиска, функция scanf() переходит к следующему спецификатору формата. Множество поиска определяется списком символов, заключённых в квадратные скобки. Перед открывающей скобкой ставиться знак %. Давайте рассмотрим это на примере.
void main(void)
char str1[10], str2[10];
scanf(«%[0123456789]%s», str1, str2);
printf(«\n%s\n%s»,str1,str2);
>
Введём набор символов:
12345abcdefg456
На экране программа выдаст:
12345
abcdefg456
При задании множества поиска можно также использовать символ «дефис» для задания промежутков, а также максимальную ширину поля ввода.
Можно также определить символы, которые не входят в множество поиска. Перед первым из этих символов ставиться знак ^. Множество символов различает строчные и прописные буквы.
Напомню, что при использовании функции scanf(), ей в качестве параметров нужно передавать адреса переменных. Выше был написан код:
char str[80]; // массив на 80 символов
scanf(«%s»,str);
Обратите внимание на то, что перед str не стоит символ &. Это сделано потому, что str является массивом, а имя массива — str является указателем на первый элемент массива. Поэтому знак & не ставиться. Мы уже передаем функции scanf() адрес. Ну проще говоря str это адрес в памяти компьютера где будет храниться значение первого элемента массива.
Пример 1.
Эта программа выводит на экран запрос «Сколько вам лет?:» и ждёт ввода данных. Если, например, ввести число 20, то программа выведет строку «Вам 20 лет.». При вызове функции scanf(), перед переменной age мы поставили знак &, так как функции scanf() нужны адреса переменных. Функция scanf() запишет введённое значение по указанному адресу. В нашем случае введённое значение 20 будет записано по адресу переменной age.
void main(void)
int age;
printf(«\nСколько вам лет?:»);
scanf(«%d»,&age);
printf(«Вам %d лет.», age);
>
Пример 2.
Программа калькулятор. Этот калькулятор может только складывать числа. При вводе 100+34 программа выдаст результат: 100+34=134.
void main(void)
int x, y;
Пример 3.
Этот пример показывает как установить ширину поля считывания. В нашем примере ширина поля равна пяти символам. Если вы введёте строку с большим количеством символов, то все символы после 5-го будут отброшены. Обратите внимание на вызов функции scanf(). Знак & не стоит перед именем массива name так как имя массива name является адресом первого элемента массива.
void main(void)
char name[5];
printf(«\nВведите ваш логин (не более 5 символов):»);
scanf(«%5s», name);
printf(«\nВы ввели %s», name);
>
Пример 4.
Последний пример в этой статье показывает как можно использовать множество поиска. После запуска программы введите число от 2 до 5.
void main(void)
char bal;
printf(«Ваша оценка 2,3,4,5:»);
scanf(«%[2345]», &bal);
printf(«\nОценка %c», bal);
>
Форматированный ввод и вывод
Теги: Форматированный ввод, форматированный вывод, printf, scanf, fgets, getch, строка формата, спецификатор формата, флаги, управляющие символы.
Форматированный вывод
Сегодня мы рассмотрим две важные функции форматированного ввода и вывода. Устройство и работу этих функций полностью можно понять только после изучения работы с указателями и функций с переменным числом параметров. Но пользоваться этими функциями необходимо уже сейчас, так что некоторые моменты придётся пропустить.
Функция форматированного вывода printf получает в качестве аргументов строку формат и аргументы, которые необходимо вывести в соответствии с форматом, и возвращает число выведенных символов. В случае ошибки возвращает отрицательное значение и устанавливает значение ferror. Если произошло несколько ошибок, errno равно EILSEQ.
int printf (const char * format, . );
#include #include void main() < //функция не получает никаких аргументов, кроме строки printf("Hello world"); getch(); >
Функция проходит по строке и заменяет первое вхождение % на первый аргумент, второе вхождение % на второй аргумент и т.д. Далее мы будем просто рассматривать список флагов и примеры использования.
Общий синтаксис спецификатора формата
%[флаги][ширина][.точность][длина]спецификатор
Спецификатор – это самый важный компонент. Он определяет тип переменной и способ её вывода.
| Спецификатор | Что хотим вывести | Пример |
|---|---|---|
| d или i | Целое со знаком в в десятичном виде | 392 |
| u | Целое без знака в десятичном виде | 7235 |
| o | Беззнаковое в восьмеричном виде | 657 |
| x | Беззнаковое целое в шестнадцатеричном виде | 7fa |
| X | Беззнаковое целое в шестнадцатеричном виде, верхний регистр | 7FA |
| f или F | Число с плавающей точкой | 3.4563745 |
| e | Экспоненциальная форма для числа с плавающей точкой | 3.1234e+3 |
| E | Экспоненциальная форма для числа с плавающей точкой, верхний регистр | 3.1234E+3 |
| g | Кратчайшее из представлений форматов f и e | 3.12 |
| G | Кратчайшее из представлений форматов F и E | 3.12 |
| a | Шестнадцатеричное представление числа с плавающей точкой | -0xc.90fep-2 |
| A | Шестнадцатеричное представление числа с плавающей точкой, верхний регистр | -0xc.90FEP-2 |
| c | Буква | a |
| s | Строка (нуль-терминированный массив букв) | Hello World |
| p | Адрес указателя | b8000000 |
| n | Ничего не печатает. Аргументом должен быть указатель на signed int. По этому адресу будет сохранено количество букв, которое было выведено до встречи %n | |
| % | Два идущих друг за другом процента выводят знак процента | % |
#include #include void main()
Строка формата также может включать в себя следующие необязательные суб-спецификаторы: флаг, ширина, .точность и модификатор (именно в таком порядке).
| Флаг | Описание |
|---|---|
| — | Выключка влево на заданное шириной значение |
| + | Явно указывать знак у числа, даже для положительных чисел |
| (пробел) | Если знак не будет выведен, то вставляет пробел перед выводимым числом |
| # | Когда используется вместе с o, x или X, вставляет перед числом 0, 0x или 0X Когда используется со спецификаторами a, A, e, E, f, F, g или G, вставляет десятичную точку, даже если после неё нет десятичных знаков. |
| 0 | Вставляет нули, когда объявлен спецификатор ширины |
| Ширина | Описание |
|---|---|
| (число) | Минимальное количество знаков, которое необходимо вывести. Если в числе меньше знаков, то вставляет пробелы (или нули) |
| * | Ширина не указана в строке формата, она передаётся отдельно в виде аргумента, который должен предшествовать выводимому числу |
| .Точность | Описание |
|---|---|
| .число | Для спецификаторов целых (d, i, o, u, x, X) точность определяет минимальное количество знаков, которое необходимо вывести. Если значение короче, то выводятся нули перед числом. Значение не обрезается, даже если оно длиннее. Точночть 0 означает, что для значения 0 ничего не выводится. Для спецификаторов чисел с плавающей точкой (a, A, e, E, f, F) это число знаков, которые необходимо вывести после десятичной точки (по умолчанию 6). Для g и G — это число значащих разрядов, которые необходимо вывести. Для s — выводится указанное число символов. По умолчанию выводятся все символы до первого нулевого. Если число не стоит, то по умолчанию точность равна 0 |
| .* | Точность не указана в строке формата, она передаётся отдельно в виде аргумента, который должен предшествовать выводимому числу |
#include #include void main()
Суб-спецификатор длины изменяет длину типа. В случае, если длина не совпадает с типом, по возможности происходит преобразование до нужного типа.
| спецификаторы | |||||||
|---|---|---|---|---|---|---|---|
| Длина | d, i | u o x X | f F e E g G a A | c | s | p | n |
| (none) | int | unsigned int | double | int | char* | void* | int* |
| hh | signed char | unsigned char | signed char* | ||||
| h | short int | unsigned short int | short int* | ||||
| l | long int | unsigned long int | wint_t | wchar_t* | long int* | ||
| ll | long long int | unsigned long long int | long long int* | ||||
| j | intmax_t | uintmax_t | intmax_t* | ||||
| z | size_t | size_t | size_t* | ||||
| t | ptrdiff_t | ptrdiff_t | ptrdiff_t* | ||||
| L | long double | ||||||
#include #include void main()
Форматированный ввод
Рассмотрим форматированный ввод функцией scanf.
int scanf(const char*, . )
Функция принимает строку формата ввода (она похожа на строку формата printf) и адреса, по которым необходимо записать считанные данные. Возвращает количество успешно проинициализированных аргументов.
Формат спецификатора ввода
%[*][ширина][длинна]спецификатор
| Спецификатор | Описание | Выбранные символы |
|---|---|---|
| i, u | Целые | Произвольное число цифр (0-9), возможно, начинающихся с + или -. Если число начинается с 0, то считывается в восьмеричном формате, если с 0x, то в шестнадцатеричном. |
| d | Десятичное целое | Произвольное число цифр (0-9), возможно, начинающихся с + или -. |
| o | восьмеричное целое | Произвольное число цифр (0-7), возможно, начинающихся с + или -. |
| x | Шестнадцатеричное целое | Произвольное число цифр (0-F), возможно, начинающихся с + или — и префикса 0x или 0X. |
| f, e, g | Число с плавающей точкой | Число, состоящее из набора цифр 0-9, возможно с десятичным разделителем (точкой). Возможно также представление в экспоненциальной форме. C99 позволяет также вводить число в шестнадцатеричном формате. |
| a | ||
| c | Символ | Если ширина не передана, то считывает один символ. Если ширина передана, то считывает нужное количество символов и размещает их в массиве БЕЗ терминального символа на конце. |
| s | Строка | Считывает все не пробельные символы. Если указана ширина, то не более n символов. Ставит на место n+1 символа терминальный. |
| p | Адрес указателя | Последовательность символов, трактуемая как адрес указателя. Формат зависит от реализации, но совпадает с тем, как выводит printf с ключом p |
| [символы] | Множество символов | Считывает только те символы, которые записаны в квадратных скобках, С99 |
| [^символы] | Множество символов | Считывает только те символы, которые не указаны в квадратных скобках, С99 |
| n | Ничего не считывает | Сохраняет число уже считанных символов по указанному адресу |
Как и в printf, ширина, заданная символом * ожидает аргумента, который будт задавать ширину. Флаг длина совпадает с таким флагом функции printf.
#include #include void main() < int year, month, day; char buffer[128]; int count; //Требует форматированного ввода, например 2013:12:12 printf("Enter data like x:x:x = "); scanf("%d:%d:%d", &year, &month, &day); printf("year = %d\nmonth = %d, day = %d\n", year, month, day); //Считываем строку, не более 127 символов. При считывании в массив писать & не надо, //так как массив подменяется указателем printf("Enter string = "); scanf("%127s", buffer); printf("%s", buffer); getch(); >
Кроме функций scanf и printf есть ещё ряд функций, которые позволяют получать вводимые данные
int getch() [aka _getch(), getchar()] — возвращает введённый символ, при этом не выводит его на консоль.
#include #include void main() < char c = 0; do < c = getch(); printf("%c", c); >while (c != 'q'); >
char * fgets ( char * str, int num, FILE * stream ) — функция позволяет считывать строку с пробельными символами. Несмотря на то, что она работает с файлом, можно с её помощью считывать и из стандартного потока ввода. Её преимущество относительно gets в том, что она позволяет указать максимальный размер считываемой строки и заканчивает строку терминальным символом.
#include #include #include void main() < char buffer[128]; //Считываем из стандартного потока ввода fgets(buffer, 127, stdin); printf("%s", buffer); //Этим можно заменить ожидание ввода символа scanf("1"); >
Это не полный набор различных функций символьного ввода и вывода. Таких функций море, но очень многие из них небезопасны, поэтому перед использованием внимательно читайте документацию.
Непечатные символы
В си определён ряд символов, которые не выводятся на печать, но позволяют производить форматирование вывода. Эти символы можно задавать в виде численных значений, либо в виде эскейп-последовательностей: символа, экранированного обратным слешем.
| Последовательность | Числовое значение | Результат |
|---|---|---|
| \a | 0x07 | Звуковой сигнал |
| \b | 0x08 | Перевод каретки на одно значение назад |
| \f | 0x0c | Новая страница |
| \n | 0x0a | Перевод строки, новая строка |
| \r | 0x0d | Возврат каретки |
| \t | 0x09 | Табуляция |
| \v | 0x0b | Вертикальная табуляция |
| \» | 0x22 | Двойная кавычка |
| \\ | 0x5с | Обратный слеш |
#include #include void main() < char backspace = 0x08; //Выводим с использованием символа переноса строки printf("Hello\nWorld\n"); //Выводим символ переноса строки через его значение printf("Hello%cWorld\n", 0x0a); //"Выводим" сигнал printf("\a"); //Выводим сигнал, как символ printf("%c", '\a'); //Выводим сигнал через шестнадцатеричное значение printf("%c", 0x07); printf("This is sparta. \b\b%c", backspace); printf(" "); getch(); >
ru-Cyrl 18- tutorial Sypachev S.S. 1989-04-14 sypachev_s_s@mail.ru Stepan Sypachev students

Всё ещё не понятно? – пиши вопросы на ящик
Printf c что это
Печатает отформатированный вывод в стандартном потоке вывода данных (функция библиотеки С и С++).
Синтаксис
int printf( const char *format [, argument]. );
int wprintf( const wchar_t *format [, argument]. );
Параметры
format
argument
Возвращаемое значение
Возвращает число напечатанных символов или отрицательное значение, если происходит ошибка.
Замечания
Функция printf форматирует и печатает ряд символов и значений в стандартном потоке вывода данных — stdout. Если параметры следуют за строкой format, то форматирующая (format) строка должна содержать спецификации, которые определяют формат вывода для параметров. Функции printf и fprintf ведут себя тождественно за исключением того, что printf печатает выводимые данные stdout, а не в целевой тип файла (FILE).
Функция wprintf — широкосимвольная версия printf (для Unicode); format — широкосимвольная строка. Функции wprintf и printf во всем остальном ведут себя тождественно.
Унифицированно-текстовые стандартные отображения
Стандартный TCHAR.H
_UNICODE & _MBCS не определен
Параметр format состоит из обычных символов, последовательностей escape, и (если параметры следуют за параметром format), то спецификации формата. Обычные символы и последовательности escape копируются в stdout в порядке их поступления. Например, строка
printf("Line one\n\t\tLine two\n");
Line one Line two
Спецификации формата всегда начинаются со знака процента (%) и читается слева направо. Когда функция printf встречается с первой спецификацией формата (если она есть), то преобразует значение первого параметра после format и выводит его соответственно. Вторая спецификация формата заставляет второй параметр быть преобразованным и выведенным, и так далее. Если имеется больше параметров, чем есть их спецификаций, дополнительные параметры игнорируются. Результаты не определяются, если недостаточно параметров для всех спецификаций формата.
Поля спецификации формата: функции printf и wprintf
Cпецификации формата, которые состоят из дополнительных и затребованных полей, имеют нижеследующую форму:
Каждое поле спецификации формата — это единичный символ или число, показывающее конкретный вариант выбора формата. Самая простая спецификация формата содержит в себе только знак процента и символ типа — type (например, %s). Если знак процента сопровождается символом, у которого нет никакого значения как поля формата, символ копируется в stdout. Например, чтобы напечатать символ знака процента, используйте %%.
Дополнительные поля, которые показываются перед символом type, управляют другими аспектами форматирования, следующим образом:
Затребованный символ, который определяет, понимается ли связанный параметр как символ, строка или число (см. таблицу Поля типов символов printf.
flags
Дополнительный символ или символы, которые управляют выравниванием вывода данных и печати знаков, пробелов, десятичных запятых, и октальных и шестнадцатеричных префиксов (см. таблицу Флажки символов). Более чем один флажок может применяться в спецификации формата.
width
Дополнительное число, которое указывает минимальное число выводимых символов (см. printf — Спецификация ширины).
precision
Дополнительное число, которое указывает максимальное число символов, напечатанных для всех или части полей вывода, или минимальное число цифр, напечатанных для целого значения (см.таблицу Как значения точности оказывают влияние на тип символа).
h | l | I | I32 | I64
Дополнительные префиксы для type, которые указывают размер параметра (см. таблицу Префиксы размера для printf и wprintf Спецификаторов типа формата).
printf( name ); // Опасность! Если имя будет содержать "%s", то программа потерпит крах
Вместо этого сделайте вот это:
printf( "%s", name );
Демонстрационный пример
// crt_printf.c /* Эта программа использует функции printf и wprintf * чтобы выполнить форматированный вывод данных. */ #include stdio.h> int main( void ) char ch = 'h', *string = "computer"; int count = -9234; double fp = 251.7366; wchar_t wch = L'w', *wstring = L"Unicode"; /* Показывает целые числа. */ printf( "Integer formats:\n" " Decimal: %d Justified: %.6d Unsigned: %u\n", count, count, count, count ); printf( "Decimal %d as:\n Hex: %Xh C hex: 0x%x Octal: %o\n", count, count, count, count ); /* Показывает в различных основаниях системы счисления. */ printf( "Digits 10 equal:\n Hex: %i Octal: %i Decimal: %i\n", 0x10, 010, 10 ); /* Показывает символы. */ printf("Characters in field (1):\n%10c%5hc%5C%5lc\n", ch, ch, wch, wch); wprintf(L"Characters in field (2):\n%10C%5hc%5c%5lc\n", ch, ch, wch, wch); /* Показывает строки. */ printf("Strings in field (1):\n%25s\n%25.4hs\n %S%25.3ls\n", string, string, wstring, wstring); wprintf(L"Strings in field (2):\n%25S\n%25.4hs\n %s%25.3ls\n", string, string, wstring, wstring); /* Показывает действительные числа. */ printf( "Real numbers:\n %f %.2f %e %E\n", fp, fp, fp, fp ); /* Показывает указатели. */ printf( "\nAddress as: %p\n", &count); /* Подсчет выведенных для печати символов. */ printf( "\nDisplay to here:\n" ); printf( "1234567890123456%n78901234567890\n", &count ); printf( " Number displayed: %d\n\n", count ); >
Вывод данных
Форматы целых чисел: Десятичный: -9234 Выравненный: -009234 Беззнаковый: 4294958062 Десятичный -9234 как: Hex(шестнадцатиричный): FFFFDBEEh C hex: 0xffffdbee Octal(восьмиричный): 37777755756 Цифра 10 эквивалентна: Hex: 16 Octal: 8 Decimal: 10 Символов в поле (1): h h w w Символов в поле (2): h h w w Строк в поле (1): computer comp Unicode Uni Строк в поле (2): computer comp Unicode Uni Действительные числа: 251.736600 251.74 2.517366e+002 2.517366E+002 Адрес как: 0012FEE0 Вывод на экран здесь: 123456789012345678901234567890 Число показанное на экране: 16
Смотри также
Процедуры поддержки плавающей запятой | Процедуры потоков ввода-вывода (I/O) | Локальные процедуры | функции fopen | fprintf | scanf | sprintf | vprintf | Процедуры времени исполнения программы и эквиваленты .NET Framework
Требования
Процедуры
Требуется заголовочный файл
Совместимость
Дополнительную информацию о совместимости см. в статье Совместимость в главе Введение.
Библиотеки
Все версии библиотек времени исполнения программы C.
Printf c что это
Перевод статьи «Secrets of printf» [1], статья посвящена практическому применению оператора вывода printf.
Оператор printf — это просто функция языка C, которая выполняет форматированную печать неких значений, параметров функции. «Форматированную» — означает, что перед выводом параметров на печать параметры функции преобразуются в текст по особым правилам (формату), задаваемым специальной строкой, так называемой строкой форматирования. Точно такая же функция printf есть и на языке PERL. В этой заметке сделана попытка объяснить, как работает printf, и как правильно разработать соответствующую строку форматирования для любого случая.
[1. Основные понятия]
В старые времена программисты должны были писать свои собственные подпрограммы для ввода и вывода чисел. По сути это было не очень сложным делом. Сначала надо было выделить массив текстовых символов для хранения результата, затем просто разделить число на 10, запомнить остаток, добавить 0x30 для получения ASCII кода цифры, и сохранить цифру в конец массива. Далее эту процедуру нужно было повторить, чтобы найти все десятичные цифры числа. Затем нужно было вывести массив на печать. Все просто, не правда ли?
Однако несмотря на то, что просто (для гения типа Эйнштейна), однако все еще требует применения некоторых усилий. И что мы будем делать в более сложных случаях при проверке ошибок, или при выводе отрицательных чисел? Чтобы решить эти проблемы, программисты создали специальные библиотеки с предварительно написанными функциями вывода. И это было неплохо. В конечном счете самые популярные из этих функций были канонизированы для того, чтобы составить «стандартные» библиотеки.
Это означало, что теперь программистам не нужно было снова и снова выдумывать подпрограммы для печати чисел. Это также означало, что самые любимые опции вывода также должны были бы стать стандартными.
Так родился printf.
[2. Простая печать]
В самом простом случае функция printf получает один аргумент: строка символов, которая должна быть напечатана. Как ясно из названия, эта строка состоит из символов, каждый из которых будет выведен именно так, как он появляется в строке. Так, оператор printf(«xyz»); должен просто вывести сначала x, затем y, и наконец z. Это не является по-настоящему «форматированной» печатью (formatted printf), однако это базовая операция, которую может произвести printf.
2.1. «Натуральные» специальные символы
Чтобы идентифицировать начало строки, мы применили двойные («) кавычки в её начале. Чтобы идентифицировать конец строки, мы поместили двойные кавычки также и в конец строки. Но как быть, если нам нужно напечатать также и двойные кавычки? Мы не можем просто поместить двойные кавычки в печатаемую строку, потому что тогда этот символ будет ошибочно задавать маркер конца строки. Таким образом, двойные кавычки стали специальным символом. Для них уже не работает правило печатаю-то-что-вижу. Как все-таки напечатать двойные кавычки?
Различные языки программирования применяют разные способы для решения этой проблемы. Некоторые требуют, чтобы специальный символ был введен дважды. Язык C использует обратный слеш (делительная черта, \) в качестве управляющего символа (escape character), для изменения значения следующего за ним символа. Таким образом, для печати двойных кавычек нужно указать обратный слеш и за ним двойную кавычку (\»). Чтобы напечатать сам обратный слеш, то его нужно ввести дважды. Таким образом, первый обратный слеш означает «следующий символ имеет альтернативное значение», и второй обратный слеш теперь означает «напечатать обратный слеш».
Без обратного слеша специальные символы имеют свое натуральное специальное назначение. С обратным слешем они печатаются так, как видятся. В таблице приведен частный список примеров использования специальных символов.
| \ | escape, управляющая последовательность для следующего символа |
| \\ | печатается обратный слеш |
| « | обозначает начало или конец строки |
| \» | печатаются двойные кавычки |
| ‘ | начало или конец символьной константы |
| \’ | печатается одинарная кавычка |
| % | начало спецификации формата |
| \% | печатается символ процента |
| %% | также печатается символ процента |
2.2. Альтернативные специальные символы
Однако еще у нас есть символы, которые печатаются без обратного слеша как обычно, но когда слева к ним добавляется обратный слеш, они становятся также спецсимволами. Например, это символ новой строки (new line, или line feed LF, код ASCII 0x0A). Чтобы напечатать букву n, нам нужно просто указать в строке n. Чтобы перевести печать на новую строку, мы должны напечатать \n, что вовлекает альтернативное значение для n (новая строка). В следующей таблице приведен список таких альтернативных спецсимволов.
| \a | звуковой сигнал, предупреждение (звоночек, bell) |
| \b | backspace, вернуться на 1 символ назад (затереть символ) |
| \f | form feed, переход на новый лист |
| \n | newline, новая строка (linefeed, перевод строки, код ASCII 0x0D, переход печати на новую строку) |
| \r | carriage return, возврат каретки (CR, код ASCII 0x0D, позиция печати возвращается на начало строки) |
| \t | tab, табуляция по горизонтали |
| \v | vertical tab, вертикальная табуляция |
[3. Как задавать формат вывода числа (Format Specifications)]
Настоящая сила printf раскрывается при выводе на печать переменных. К примеру, мы можем указать спецификатор формата %d . Если такой спецификатор присутствует в строке, то мы должны предоставить число в качестве второго параметра функции printf. Функция printf сделана так, что может принимать неограниченное количество параметров, если это необходимо (printf относится к функциям с переменным количеством параметров). Пример ниже показывает, как это происходит.
int age; age = 25; printf ( "I am %d years old\n", age );
В этом простом примере функция printf имеет 2 аргумента. Первый аргумент — строка «I am %d years old\n» (в ней содержится спецификатор формата %d ). Вторым аргументом является целое число age.
3.1. Список аргументов
Когда printf обрабатывает свои аргументы (список аргументов, отделенных друг от друга запятыми), он начинает печатать символы, которые находит в левом аргументе, символ за символом. Когда в этом процессе попадается символ процента (%), то printf знает, что это спецификатор формата — специальный набор символов, который задает, как надо вывести число. Следующее по порядку с списке аргументов число выводится так, как указано в спецификаторе формата. Затем процесс обработки символов (вывод их на печать) первого аргумента продолжается. Можно указать в строке 1 аргумента функции printf несколько спецификаторов формата. В этом случае 1 спецификатор будет выводить первый дополнительный аргумент, 2 спецификатор второй дополнительный аргумент и так далее, до конца строки. Вот еще один пример (указано 2 спецификатора формата и два дополнительных аргумента функции printf):
int x = 5, y = 10;
printf ( "x is %d and y is %d\n", x, y );
3.2 Символ процента (Percent, %)
Каждый спецификатор формата начинается со знака процента, и заканчивается буквой. Буквы выбраны так, что они имеют некое мнемоническое обозначение для используемого формата. Вот список некоторых мнемоник формата:
| %c | выводит на печать одиночный символ (character) |
| %d | выводит на печать десятичное число (представление числа с основанием 10) |
| %e | выводит на печать числа с плавающей запятой (floating-point) в экспоненциальном формате |
| %f | выводит на печать числа с плавающей запятой (floating-point) |
| %g | выводит на печать числа с плавающей запятой (floating-point) в общем формате |
| %i | выводит на печать десятичного целого числа (представление числа с основанием 10) |
| %o | выводит на печать числа в восьмеричном формате (представление числа с основанием 8) |
| %s | выводит на печать строки символов |
| %u | выводит на печать целое десятичное число без знака (представление числа с основанием 10) |
| %x | выводит на печать целого шестнадцатеричного числа (представление числа с основанием 16) |
| %% | выводит на печать символ процента (можно использовать для этого также \%) |
Самый простой вывод десятичного числа (целого и с плавающей точкой) требует указания только %d. В таблице приведены некоторые примеры аргументов printf и полученных результатов.

Имейте в виду, что в случае использования %d размер получаемой строки заранее не известен. Функция printf сгенерирует строку такого размера, какой нужен.
3.3. Опция ширины формата (Width Option)
Как уже упоминалось, простой печати чисел недостаточно. Есть другие желаемые опции. Возможно, самая важная из них — опция ширины формата. Если указать спецификатор формата %5d, то будет гарантировано, что вывод числа всегда займет 5 символьных позиций (если нужно, то больше, но никак не меньше). Эта возможность очень полезна при печати таблиц, потому что и большие, и маленькие числа займут в строке одинаковое место. Не так давно вся печать была моноширинной (monospaced, все символы по точкам в ширину были одинаковы), т. е. и символ w, и символ i занимали одинаковое место в строке по ширине. Это остается общим правилом в текстовых редакторах, используемых программистами.
Чтобы напечатать десятичное число определенной (как минимум заданной, не меньше) ширины, скажем шириной в 5 пробелов, спецификатор формата должен быть %5d. В таблице приведены простые примеры использования опции ширины (пробелы для наглядности показаны нижней квадратной скобкой).

Имейте в виду, что результат вывода будет дополнен слева пробелами до необходимой указанной ширины (для примеров в таблице это 5 символов). Слишком большие числа, которые требуют для печати большее количество символов, будут выведены полностью.
Чтобы добиться нормального использования, поле опции ширины должно быть указано таким, чтобы удовлетворять максимальному размеру ожидаемого выводимого числа. Например, если Ваши числа могут состоять из 1, 2 или максимум 3 цифр, то формат %3d подойдет. Опция ширины будет работать неправильно, если потребуется напечатать число, которое слишком большое, чтобы уместиться в заданную ширину поля. Функция printf примет решение вывести такие числа полностью, даже если они займут место больше, чем задано в спецификаторе ширины формата. Так сделано потому, что лучше вывести правильный ответ, пусть даже некрасиво, чем напечатать урезанный (неправильный) результат, и потом гадать, где же произошла ошибка.
3.4. Заполнение лишнего места
Когда печатается маленькое по размеру число наподобие 27 в поле формата %5d, встает вопрос — чем и как заполнить 3 другие (пустые) места печати. Цифры 27 можно напечатать по-разному: вывести в первых двух позициях, в последних двух позициях, или где-то посередине. Также пустые места могут быть заполнены не просто пробелами, а звездочками (***27, или 27***, или **27*), или знаками доллара ($$$27), или символами равенства (===27), или начальными нулями (наподобие 00027).
Эти дополнительные символы часто называют символами «проверочной защиты» (check protection), потому что они предназначены помешать плохим парням изменить печатаемую сумму в долларах. Относительно просто поменять заполнение пробелами на что-то другое. Гораздо сложнее подменить символ звездочки, знак доллара и ли символ равенства.
Функция printf предоставляет заполнение пространства пробелами (слева или справа), и заполнение нулями (только слева). Если Вам нужна check protection, или центрирование, то нужно использовать какие-то другие дополнительные методы. Но даже без check protection или центрирования printf
все равно имеет впечатляющую коллекцию опций форматирования.
3.5. Опция выравнивания (Justify Option)
Вывод на печать чисел функцией printf может быть выровнена влево (left-justified, напечатана в поле слева) или вправо (right-justified, напечатано в поле справа). Наиболее естественной выглядит печать чисел выровненными вправо, с дополнением пробелами слева. Так работает спецификатор формата %5d, он означает: напечатать число по основанию 10 в поле шириной 5 символов, и цифры числа выровнять по правому краю, слева дополнив нужным количеством пробелов.
Чтобы сделать число выровненным слева, к спецификатору формата нужно добавить знак минуса (-). Чтобы напечатать число в поле шириной в 5 символов, с выравниванием по левому краю спецификатор формата будет %-5d. В таблице приведены некоторые примеры использования левого выравнивания.

Так же, как и раньше, для коротких чисел результат будет дополнен справа пробелами. Слишком большие числа будут выведены без дополнения пробелами и не урезанные.
3.6. Заполнение лидирующими нулями (Zero-Fill Option)
Чтобы печать даты выглядела красиво и качественно, обычно одиночные цифры даты и месяца дополняют слева нулем. Это и есть «лидирующий ноль». Мы можем написать May 5, 2003, или как принято в США 05/05/2003. Можно написать также дату в виде 2003.05.05. Обратите внимание, что лидирующий ноль не изменяет значение дат, а просто добавляет наглядности. Таким способом отформатированная дата хорошо выглядит в списке.
Когда используется zero-filled (заполнение лидирующими нулями), нули всегда добавляются спереди, и результат получается выровненным как по левому, так и по правому краю. В этом случае знак минуса не дает эффекта. Чтобы вывести число в 5 позиций с дополнением нулями слева применяйте спецификатор формата %05d. В таблице показаны примеры использования и полученные результаты.

Короткие числа будут дополнены лидирующими нулями. Числа большого размера будут напечатаны как есть, без изменения.
3.7. Забава со знаками «плюс»
Отрицательные числа всегда будут выведены со знаком минуса (-). Положительные числа и нули обычно не печатаются со знаком, однако Вы можете это задать принудительно. Символ плюса (+) в спецификаторе формата делают такой запрос. Чтобы напечатать число со знаком в поле шириной 5 символов, спецификатор формата должен быть %+5d. В таблице показаны примеры использования и полученные результаты.

Имейте в виду, что 0 трактуется как положительное число. Короткие числа будут дополнены нужным количеством указанных заполнителей. Слишком большие числа будут выведены без дополнения и не урезанные.
Плюс и минус не связаны друг с другом. Они оба могут появляться в спецификаторе формата.
3.8. Невидимый знак «плюс»
Знак + немного причудлив, он может быть невидимым. В этом случае вместо печати + на положительных числах (и при печати 0), мы напечатаем пробел, где этот знак должен был бы находиться. Это может оказаться полезным при печати выровненных влево чисел, если Вы хотите, чтобы знак минуса значительно выделялся. В примерах ниже показаны два альтернативных варианта.

Помните о том, что спецификатор формата %-5d даст нам другой результат, который мы уже рассматривали ранее (он показан здесь снова для наглядности):

Имейте в виду, что знак + исчезает, но все еще занимает место слева от числа. Имейте в виду также, что мы можем скомбинировать некоторые опции в одном и том же спецификаторе формата. В этом случае мы имеем скомбинированные опции +, -, 5, или пробел, -, 5, или просто -, 5.
3.9. +, пробел и 0
Здесь приведен другой пример одновременного комбинирования некоторых опций в одном спецификаторе формата. Использование спецификаторов формата % 05d или %0 5d дадут нам следующие результаты:

Использование спецификаторов формата %+05d или %0+5d дадут нам следующие результаты:

Когда мы одновременно комбинируем + и пробел в одном спецификаторе формата, пробелы организуют пространство для знака, которое занимал бы знак +. Результат тот же, если бы даже пробел не был бы указан. Символ + имеет приоритет над пробелом.
3.10. Общие замечания по формату вывода
Опции вывода также называют флагами (flags), и между собой они могут появляться в любом порядке. В таблице приведен их частный список.

После опций если нужно, может быть указана минимальная ширина поля вывода.
[4. Вывод на печать строк]
Опция %s позволяет нам печатать строку внутри строки. Ниже дан пример.
char * grade;
if ( year == 11 ) grade = "junior"; printf ( "%s is a %s\n", "Fred", grade );
Флаг левого выравнивания может быть применен к строкам, однако конечно же дополнение слева нулями (zero fill), знак +, и невидимый + являются бессмысленными.

[5. Вывод чисел с плавающей точкой (Floating Point)]
Числа с плавающей точкой наподобие 3.1415 содержат внутри себя точку. Обычные целые числа типа 27 не имеют такой точки.
Для печати чисел с плавающей точкой (float, double) флаги и правила работают точно так же, как и для целых чисел, но еще есть несколько новых опций. Самая важная указывает, какое количество цифр может появиться после десятичной точки. Это количество цифр называется точностью (precision) числа.
В обычной коммерции используются прайсы, где цены часто фигурируют как целые доллары или доллары и центы (precision составляет 0 или 2 цифры). Для цены на бензин цены упоминаются как доллары, центы, и десятая доля от цента (precision составляет 3 цифры). Ниже приведены примеры, как может быть выведено на печать число e=2.718281828.

Обратите внимание, что если в спецификаторе формата указаны точка и число, то это число (precision) указывает, сколько чисел должно появиться после десятичной точки.
Имейте в виду, что если не указаны точка и precision для %f, то по умолчанию будет приведен формат %.6f (6 цифр после десятичной точки).
Имейте также в виду, что если указана precision 0, то десятичная точка также исчезает. Если Вы хотите её вернуть, то нужно это сделать принудительно в виде простого текста (после спецификатора формата %f).
Мы можем указать оба и ширину (width), и точность (precision) одновременно в одном спецификаторе формата. Имейте в виду, что 5.2 означает общую длину 5, с 2 цифрами после десятичной точки. Самая распространенная ошибка, когда думают, что это означает 5 цифр до точки и 2 цифры после точки, но это неправильно. Будьте внимательны.

Можно также комбинировать precision с флагами, с которыми мы уже познакомились, чтобы указать левое выравнивание, дополнение слева нулями, применение знака +, и т. д.

[6. Как лучше всего разрабатывать формат]
Если Вы придумываете спецификатор формата, то первый шаг, который нужно сделать — решить, что именно Вы печатаете. Если это целое число (unsigned char, short, int, long), число с плавающей точкой (float, double), строка (char []) или одиночный символ (char), то Вы должны выбрать соответствующий спецификатор для базового типа формата.
Второй важный вопрос — какой ширины в символах должна быть печатаемое поле. Обычно это определяет самое большое по величине печатаемое число, которое Вы ожидаете при нормальной работе программы. Иногда этот размер определяется шириной предоставленного поля в форме или таблице (как например, в поле на кассовом чеке или на таблице счета-фактуры).
Решите, что Вы хотели бы увидеть на печати в различных ситуациях, в которых работает программа. В этой статье мы часто рассматривали результаты использования маленького положительного числа, маленького отрицательного числа, положительного числа вышедшего за установленный размер, отрицательного числа вышедшего за установленный размер. Опцию ширины Вы должны задать так, чтобы она хорошо подходила как к большим (но не превышающим максимальный размер), так и к малым числам. В самом простейшем случае можно разработать формат для корректного вывода самого большого числа, но если нужно обеспечить заданную относительную точность, то может потребоваться набор условных операторов с разными вариантами формата.
[7. Советы для тестирования]
Тест printf включает проверку появления подходящих проблем. Сам по себе алгоритм работы printf непрост для полного понимания — как будет работать вывод в разных ситуациях. Поэтому изучение тестового вывода printf даст более точную картину — что работает не так.
Вы можете сделать этот процесс нахождения ошибок очень быстрым и точным. Если Вы смотрите на результат работы функции printf с разными опциями форматирования, то можете быстро увидеть, какой спецификатор формата подходит лучше всего. Это быстро может сузить варианты форматирования до одного или двух.
7.1. Простые случаи
Можно просто увидеть, есть ли у коротких чисел лидирующие нули. Если так, то в спецификаторе формата здесь должен быть 0. Также просто увидеть, есть ли у положительных чисел знак +. Если этот так, то + должен быть и в спецификации форматирования.
7.2. Перед, между, позади
Следующее, что нужно проверить — что печатается до выводимого числа, в промежутке, и после. К примеру, В спецификации форматирования типа x%5dz, где x стоит перед числом и z за числом. Части x и z не входят в спецификатор формата, но входят как часть в печатаемый результат. Все остальное относится к тому, что печатается «между».
Для того, чтобы определить, что же печатается за числом, посмотрите на вывод отрицательного числа чрезмерно большого размера. Любые пробелы до выведенного числа и после него покажут на пробелы до и после спецификатора формата. Например, если -2035065302 печатается как __-2035065302_ (здесь для наглядности пробелы заменены на подчеркивания), то можете быть уверенными, что строка печати была наподобие __%. _ , с двумя пробелами перед и одним пробелом после спецификатора формата. Это произошло потому, что чрезмерно большое число заняло все позиции, которые были отведены в спецификаторе формата.
Как только Вы определили, что перед, и что позади, Вы можете использовать эту информацию, чтобы сделать соответствующий выбор спецификатора формата. Часто бывает, что искомый ответ сразу становится очевидным.
7.3. Невидимый знак +
Сравните между собой вывод чрезмерно большого отрицательного и такого же положительного числа. Если положительное число имеет дополнительный пробел слева, то в этом месте формат задает невидимый знак +. Если слева от числа нет дополнительного пробела, но невидимый знак не задан.
7.4. Левое выравнивание
Вычтите друг из друга то, что перед, и то что позади. Посмотрите, что осталось слева. Посмотрите на вывод маленького отрицательного числа. Где Вы видите дополнительные печатаемые пробелы? Если они находятся спереди числа, то применено правое выравнивание числа. Если они находятся позади, то число выровнено при печати влево. Если пробелы есть и спереди, и сзади, значит Вы что-то делаете неправильно.
[8. Вывод printf на печать без символа новой строки]
Библиотека стандартного вывода (stdio.h) обычно реализована так, что в stdout ничего не будет выведено, пока в потоке символов не будет обнаружен символ новой строки ‘\n’. Это создает проблемы при выходе из программы, если в выведенном сообщении не было в конце символа новой строки [3], а также при отображении строки прогресса или процентов завершения текущей операции.
Для решения этой проблемы можно использовать вызов fflush(stdout) [4]. Пример:
. wsize += UPGRADE_DATA_BLOCK_SIZE;
float percent = (float)wsize * 100 / size; printf ("\r%.0f%%", floor(percent)); fflush(stdout); .
[Заключение]
Функция printf является мощным инструментом (в умелых руках) для вывода чисел и чего-нибудь еще, хранимого в переменных. Из-за того, что инструмент мощный и имеет много возможностей, он несколько сложен в освоении. Если попытаться использовать printf наобум, без изучения документации, то его сложность часто делает невозможным понимание принципа вывода. Однако при незначительном изучении сложность может быть развернута в простые возможности, включающие width (ширина поля вывода), precision (точность), signage (управление выводом знака), justification (выравнивание) и fill (заполнение пустых мест поля вывода). Если распознать и понять эти возможности, то printf становится удобным и надежным помощником при выводе значений на печать.
[Ссылки]
1. Secrets of “printf”, Professor Don Colton, Brigham Young University Hawaii .
2. IAR EWB ARM: форматированный вывод printf библиотеки DLIB.
3. printf не выводит текст при выходе из программы.
4. c stdout print without new line? site:stackoverflow.com.