# C: стандартные функции

**stdio.h**

Модуль ввода/вывода.

**printf()** Форматированный вывод на консоль.

```c
#include <stdio.h>

int printf(const char *format, ...);
```

Первый аргумент — шаблон вывода, затем аргументы шаблона (если есть). Функция может принимать переменное число аргументов. При успешном выполнении возвращает кол-во выведенных символов, ошибки — отрицательное значение.   
Формат-строка может содержать обычные символы и спецификаторы формата, начинающиеся с символа %. Они указывают, как выводить следующие за строкой аргументы. Примеры спецификаторов:

<table border="1" id="bkmrk-%25c-%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4-%D0%BE%D1%82%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE-" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20.2977%;"></col><col style="width: 79.8215%;"></col></colgroup><tbody><tr><td>%c</td><td>вывод отдельного символа (char)</td></tr><tr><td>%s</td><td>вывод строки (char\*)</td></tr><tr><td>%c</td><td>один символ</td></tr><tr><td>%d или %i</td><td>вывод целого числа со знаком (int)</td></tr><tr><td>%u</td><td>Целое число без знака (unsigned int) в десятичной системе</td></tr><tr><td>%f или %F</td><td>вывод числа с плавающей точкой (float, double)</td></tr><tr><td>%o</td><td>вывод в восьмеричной системе</td></tr><tr><td>%x или %X</td><td>вывод в шестнадцатеричной системе (строчными и заглавными буквами соответственно)</td></tr><tr><td>%%</td><td>Символ процента %</td></tr></tbody></table>

Модификаторы типов:  
h — для short int (%hd).  
l — для long int (%ld) или double (%lf).  
L — для long double (%Lf).

Управляющие последовательности внутри строки формата тоже обрабатываются:  
\\n — перевод на новую строку;  
\\t — табуляция;  
\\\\ — обратный слеш;  
\\" — двойная кавычка.

```c
printf("Привет, %s!", "мир");  // Выведет «Привет, мир!»
```

Дополнительные возможности форматирования

Флаги:

<table border="1" id="bkmrk---%D0%B2%D1%8B%D1%80%D0%B0%D0%B2%D0%BD%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE-%D0%BB%D0%B5" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 18.9882%;"></col><col style="width: 81.131%;"></col></colgroup><tbody><tr><td>-</td><td>выравнивание по левому краю</td></tr><tr><td>+</td><td>принудительный вывод знака</td></tr><tr><td>\#</td><td>альтернативное представление для некоторых типов</td></tr></tbody></table>

Ширина поля:

%5d — число будет выведено в поле шириной в 5 символов (по умолчанию — выравнивание по правому краю).   
Точность: %.2f — число с плавающей точкой будет выведено с 2 знаками после запятой.   
Модификатор размера: %ld (длинное целое), %lld (длинное длинное).

```c
printf("%5d", 123);   // '   123'
printf("%-5d", 123);  // '123 ' (выравнивание по левому краю)
printf("%05d", 12);   // '00123' (ведущие нули)
printf("%+8.2f", 3.14159);  // ' +3.14' (знак и ширина)
```

**scanf()** Считывание данных из стандартного потока ввода (обычно с клавиатуры) и сохранение в переменных. Работает по принципу форматированного ввода: вы указываете шаблон (форматную строку), а функция интерпретирует введённые данные в соответствии с ним.

```c
int scanf(const char *format, ...);
```

Возвращает количество успешно прочитанных и присвоенных значений. Если происходит ошибка или конец файла достигнут, возвращается EOF. Однако если например вместо ожидаемой цифры будет введен символ, то он останется в буфере.

Передача адресов переменных  
Ключевой момент: функция scanf записывает данные в память, и ей нужно передать адреса переменных, куда эти данные сохранятся. Для этого перед именем переменной ставится амперсанд &amp; (операция взятия адреса).

```c
int num;
scanf("%d", &num); // Передаём адрес переменной num
```

Пример программы

```c
#include <stdio.h>

int main() {
   int age;
   printf("Введите возраст: ");
   if (scanf("%d", &age) != 1) {
      printf(stderr, "Ошибка ввода");
      return 1;
      }
   printf("Вы ввели: %d", age);
   return 0;
}
```

Интересные вещи возникают при неправильном вводе.

```c
#include <stdio.h>

int main() {
   int age;
   char my;
   printf("Введите возраст: ");
   if (scanf("%d", &age) != 1) {
      printf("Введено: %d\n", age);
      scanf("%c", &my);
      printf("Введено: %c\n", my);
      return 1;
      }
   printf("Вы ввели: %d\n", age);
   return 0;
}
```

Результат:

```bash
Введите возраст: tre
Введено: 32765
Введено: t
```

- Если переменная не инициализирована, в ней будет какой-то мусор (в данном случае 32765)
- После несоответствия формата ожидаемого ввода, переменная не меняется. То есть в age остается мусор.
- Ввод попадает в буфер, и только потом считывается scanf.
- Если в буфере будет больше элементов, чем ожидается, то в буфере останется остаток. Он будет считан при последующем вызове функции scanf.
- \\n считается символом, поэтому если последовательно получать число и символ, а ввести число и нажать Enter то во вторую переменную попадет \\n. То есть буфер после считывания не очищается.