В своей книге Практика программирования (которую стоит прочитать) Керниган и Пайк обсуждают эту проблему и решают ее, используя snprintf()
, чтобы создать строку с правильным размером буфера для переход к семейству функций scanf()
. В действительности:
int scanner(const char *data, char *buffer, size_t buflen)
{
char format[32];
if (buflen == 0)
return 0;
snprintf(format, sizeof(format), "%%%ds", (int)(buflen-1));
return sscanf(data, format, buffer);
}
Обратите внимание, это по-прежнему ограничивает входные данные размером, указанным как «буфер». Если вам нужно больше места, то вам нужно выделить память или использовать нестандартную библиотечную функцию, которая делает выделение памяти за вас.
Обратите внимание, что версия семейства функций scanf()
в POSIX 2008 (2013) поддерживает модификатор формата m
(символ назначения-назначения) для строковых входов (%s
, * 1016) *, %[
). Вместо аргумента char *
он принимает аргумент char **
и выделяет необходимое пространство для значения, которое он читает:
char *buffer = 0;
if (sscanf(data, "%ms", &buffer) == 1)
{
printf("String is: <<%s>>\n", buffer);
free(buffer);
}
Если функция sscanf()
не удовлетворяет всем спецификациям преобразования, то вся память, выделенная для %ms
-образных преобразований, освобождается до ее возврата.