Skip to the content.

Стандартные функции ввода-вывода


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, …)

Может быть еще сколько угодно параметров, такие функции называют - вариадическими.

Основа функции это форматная строка, которая состоит из:

  1. Обычных символов - любые байты, кроме нулевого и символа %
  2. Директив преобразования - которые начинаются с символа % и заканчиваются спецификатором преобразования ( например символы diouxXeEfFgGcsp%). Спецификатор указывает, какого типа значение следует извлечь из списка параметров функции.

Спецификаторы преобразований

символ значение
d i знаковое целое число в десятичной системе
o беззнаковое целое число в восьмеричной системе
u беззнаковое целое число в десятичной системе
x X беззнаковое целое число в шестнадцатеричной системе (x использует abcdef, X - ABCDEF
f F число с плавающей точкой в виде десятичной дроби
e E число с плавающей точкой в экспоненциальной форме
g G число с плавающей точкой в экспоненциальной форме либо в виде десятичной дроби в зависимости от от порядка
c целое число, которое воспринимается как однобайтный код символа, печатает символ
s адрес строки, печатает строку
p адрес типа void* и печатается в шестнадцатеричном виде
% печатает символ %, никакие параметры при этом не извлекает

Внутри директив преобразования (между % и спецификатором формата) могут быть указаны дополнительные параметры форматирования:

Число, задающее количество знакомест, означает минимальное количество знаков, которое будет использовано для представления параметра. Если представление параметра будет использовать меньше знаков, чем было выделено то:

Стоит отметить что количество знакомест, которое задаётся МИНИМАЛЬНОЕ, но никак не максимальное: printf("%3d", 1234) напечатает 1234!

После количества знакомест можно задать точность:

После точности можно задать модификатор разрядности:

Одной из интересных особенностей является то, что количество знакомест и точность можно описать не в явном виде, а взять из очередного целочисленного параметра, для этого вместо числа пишут *: printf("%*.*d", w, p, n) напечатает число n с точностью p и w знакомест.

Так же стоит отметить, что эта функция всегда float преобразует в double!

int scanf(const char * format, …)

Точно так же основывается на форматной строке, однако правила её интерпретации существенно отличаются.

Функция возвращает число, равное количеству полей, значения которых действительно были присвоены переменным. В это число не входят поля, которые были считаны с модификатором *!

Единственный флаг * - запрещает присваивание, то есть значение читается, но ни в какую память не заносится: %*i - прочитать целое число, но никуда его не записывать.

Так как функция получает адрес, в который нужно записать значение, то мы уже обязаны отличать float (%f) и double (%lf). Точно так же %d и %i для scanf разные:

Некоторые новые особенности:

%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

В С++