Стандартные функции ввода-вывода
int getchar()
Ввод символа (точнее очередной порции данных, соответствующей минимальному адресуемому размеру: зачастую один байт).
Почему возвращаемое значение типа int? Действительно, можно было бы использовать только char, однако не стоит забывать что есть еще типичная ситуация конец файла. В качестве такого значения авторы стандартной библиотеки Си выбрали -1, которую для большей ясности обозначают EOF. По итогу функция возвращает одно из 257 возможных значений (0..256 и -1). Соответственно, частая ошибка использовать char поскольку тогда программа не будет различать ситуации EOF (-1) и символ со значением 255.
#include <stdio.h>
int main()
{
int c = 0;
// приоритет присваивания ниже, чем приоритет сравнения
while ((c = getchar()) != EOF)
if (c == '\n') printf("OK\n");
return 0;
}
int putchar(int c)
Вывод символа в стандартный поток вывода. Функция возвращает код выведенного символа, если все в порядке, а если произошла ошибка, то EOF. Принимает функция код символа типа int, однако нет смысла давать ему код за пределами диапазона char, он всеравно превратит их в этот диапазон (0..255).
Форматированный ввод/вывод
int printf(const char * format, …)
Может быть еще сколько угодно параметров, такие функции называют - вариадическими.
Основа функции это форматная строка, которая состоит из:
- Обычных символов - любые байты, кроме нулевого и символа %
- Директив преобразования - которые начинаются с символа % и заканчиваются спецификатором преобразования ( например символы diouxXeEfFgGcsp%). Спецификатор указывает, какого типа значение следует извлечь из списка параметров функции.
Спецификаторы преобразований
символ | значение |
---|---|
d i | знаковое целое число в десятичной системе |
o | беззнаковое целое число в восьмеричной системе |
u | беззнаковое целое число в десятичной системе |
x X | беззнаковое целое число в шестнадцатеричной системе (x использует abcdef, X - ABCDEF |
f F | число с плавающей точкой в виде десятичной дроби |
e E | число с плавающей точкой в экспоненциальной форме |
g G | число с плавающей точкой в экспоненциальной форме либо в виде десятичной дроби в зависимости от от порядка |
c | целое число, которое воспринимается как однобайтный код символа, печатает символ |
s | адрес строки, печатает строку |
p | адрес типа void* и печатается в шестнадцатеричном виде |
% | печатает символ %, никакие параметры при этом не извлекает |
Внутри директив преобразования (между % и спецификатором формата) могут быть указаны дополнительные параметры форматирования:
- Целое число задающее количество знакомест, отведённых на вывод данного параметра
- Флаги - набор из символов ”-“ “+” “0” “#” и “пробел”
- Десятичная точка и целое число задающее точность представления
- Модификатор разрядности
Число, задающее количество знакомест, означает минимальное количество знаков, которое будет использовано для представления параметра. Если представление параметра будет использовать меньше знаков, чем было выделено то:
- По умолчанию оно будет дополнено слева пробелами:
printf("[%5d]", 12)
напечатает[ 12]
- Флаг “-“ означает, что выравнивание следует проводить по левому краю:
printf("[%-5d]", 12)
напечатает[12 ]
- Флаг “0” означает, что дополнять нужно не пробелами, а нулями:
printf("[%05d]", 12)
напечатает[00012]
- Флаг “+” означает, что число должно обязательно печататься со знаком:
printf("%+d,%+d", 12, -3)
напечатает+12,-3
- Флаг “пробел” означает, что для знака нужно оставить место, но печатать его только для отрицательных чисел:
printf("[% d],[% d]", 12, -3)
напечатает[ 12],[-3]
- Флаг “#” задаёт требование модифицировать сам формат. Т.е. он требует вывести лидирующий 0 или 0x/0X для %x %X; для e E f F требует обязательной выдачи десятичной точки, даже если дробная часть равна 0; для g G флаг запрещает удалять незначащие нули в дробной части
Стоит отметить что количество знакомест, которое задаётся МИНИМАЛЬНОЕ, но никак не максимальное: printf("%3d", 1234)
напечатает 1234
!
После количества знакомест можно задать точность:
- Для чисел с плавающей точкой:
printf("%6.3f", 0.02f)
напечатает0.020
- Для g и G - количество значащих чисел в мантисе
- Для строк - максимальное количество символов строки:
printf("%5.3s", "Hello")
напечатаетHel
- Для целых чисел - минимальное количество цифр:
printf("%.5d", 153)
напечатает00153
После точности можно задать модификатор разрядности:
- h означает, что целочисленный параметр имеет тип short или unsigned short
- l означает, что целочисленный параметр имеет тип long или unsigned long
- ll означает, что целочисленный параметр имеет тип long long или unsigned long long
- L означает, что параметр с плавающей точкой имеет тип long double
Одной из интересных особенностей является то, что количество знакомест и точность можно описать не в явном виде, а взять из очередного целочисленного параметра, для этого вместо числа пишут *: printf("%*.*d", w, p, n)
напечатает число n с точностью p и w знакомест.
Так же стоит отметить, что эта функция всегда float преобразует в double!
int scanf(const char * format, …)
Точно так же основывается на форматной строке, однако правила её интерпретации существенно отличаются.
Функция возвращает число, равное количеству полей, значения которых действительно были присвоены переменным. В это число не входят поля, которые были считаны с модификатором *!
Единственный флаг * - запрещает присваивание, то есть значение читается, но ни в какую память не заносится: %*i
- прочитать целое число, но никуда его не записывать.
Так как функция получает адрес, в который нужно записать значение, то мы уже обязаны отличать float (%f) и double (%lf). Точно так же %d и %i для scanf разные:
- Считать целое число в десятичной системе - %d
- Считать целое число в десятичной, восьмеричной (лидирующий ноль), шестнадцатеричной системе (0x либо 0X) - %i
Некоторые новые особенности:
%s - читает строку с потока до первого пробела, при это ОБЯЗАТЕЛЬНО нужно указывать количество знакомест во избежания переполнения массива, а сам массив должен иметь размер на 1 больше для завершающего нуля:
char x[80];
scanf("%79s", x); // считать до 79 символов
Если ввести 10t20, то запишет х = 10 и у = 20, а символ t в строке отбросит:
scanf("%st%s", &x, &y);
Добавляет в массив символы из множества (А, В или С) до тех пор пока не встретит символ, который не входит в множество:
char x[80];
scanf("%[ABC]", x); // ABCCDEFCCA запишет ABCC
// %[A-Z] - символы от A до Z
// %[A-Z, a-z] - и верхний и нижний регистр
// %[^ABC] - все символы кроме A, B, C
В С++
cout << setw(4) << a;
// 4 символа под выводcout.width(4);
// 4 символа под вывод