snprintf в C/C++: разбираемся с примерами

👋 Привет! В этой статье мы поговорим о функции snprintf. В отличие от функции sprintf, она принимает дополнительный аргумент: максимальная длинна C-строки, которая будет записана по адресу. Сначала мы посмотрим на сигнатуру этой функции, а потом напишем простую программу, чтобы продемонстрировать работу этой функции. В конце статьи вы найдете упражнения для закрепления материала.

Иллюстрация snprintf

Как отформатировать строку используя snprintf

Функция snprintf объявлена в заголовочном файле <stdio.h>. В C++ вы также можете использовать <cstdio>.

snprintf форматирует строку как printf, но записывает результат работы по адресу, вместо того, чтобы вывести строку в стандартный вывод. Также эта функция принимает максимальное количество байтов, которые нужно записать по адресу. Это делает ее более безопасной альтернативой функции sprintf.

Прототип этой функции выглядит следующим образом:

int snprintf(char* s, size_t n, const char* format, ...);
  • Первым аргументом функция принимает ссылку на начало строки, куда будет записан результат ее работы. В конец строки будет обязательно записан символ ее окончания - \0.
  • Вторым аргументом мы передаем максимальное количество байтов, которые будут записаны по адресу (первый аргумент). В максимальное количество байтов включается \0.
  • Третьим аргументом передается строка форматирования.
  • Далее передаются дополнительные аргументы. Их количество зависит от используемых спецификаторов формата в строке форматирования (третий аргумент).
  • Возвращает функция длину отформатированной строки (как и printf). На это число не влияет максимальное число записанных байтов n (второй аргумент).

Теперь давайте посмотрим на простой пример использования этой функции:

#include <stdio.h>

int main() {
  int a = 1, b = 2;
  char s[6];

  int n = snprintf(s, 6, "%d + %d = %d", a, b, a + b);

  printf("s = %s, n = %d", s, n);

  return 0;
}

Вывод программы:

s = 1 + 2, n = 9

Как вы можете видеть, функция обрезала строку. Только первые пять символов попали в s (только пять, потому что последний символ занимает \0).

Что будет выведено на экран?

#include <stdio.h>

int main() {
  char buffer[14];
  int a = 1234;
  int n = snprintf(buffer, 14, "число: %d", a);
  printf("buffer = %s, n = %d\n", buffer, n);
  return 0;
}
buffer = число: 1234, n = 17
buffer = число: 1, n = 16
buffer = число: 1, n = 15
buffer = число: 1234, n = 14

Часто бывает удобно использовать оператор sizeof вместо явного указания максимального количества байтов:

int n = snprintf(s, sizeof(s), "%d + %d = %d", a, b, a + b);

Результат работы будет аналогичен программе, в которой размер массива s указан явно.

Упражнения

  1. Понимание snprintf:
    Напишите программу на C++, которая запрашивает у пользователя два целых числа, а затем использует функцию snprintf для форматирования строки, которая будет содержать сумму этих чисел. Программа должна выводить исходные числа пользователя и отформатированную строку.

  2. Управление длиной строки с snprintf:
    Измените программу из предыдущего задания так, чтобы максимальная длина строки, записываемой функцией snprintf, была меньше, чем необходимо для полного вывода результата. Проанализируйте и объясните полученный результат.

  3. Сравнение snprintf и sprintf:
    Напишите программу, которая демонстрирует различия между snprintf и sprintf. В вашей программе должны быть использованы обе функции, и результаты их работы должны выводиться на экран. Проанализируйте и объясните полученные результаты.

Обсуждение