En su libro The Practice of Programming (que es bien vale la pena leer), Kernighan y Pike discutir este problema, y lo solucionan mediante el uso de snprintf()
para crear la cadena con el tamaño del búfer correcta para pasar a la scanf()
familia de funciones.En efecto:
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);
}
Nota, esto todavía limita la entrada al tamaño provisto como 'buffer'. Si necesita más espacio, debe asignar memoria o utilizar una función de biblioteca no estándar que haga la asignación de memoria por usted.
Tenga en cuenta que la versión POSIX 2008 (2013) del scanf()
familia de funciones admite un modificador de formato m
(un carácter de asignación asignación) para las entradas de cadena (%s
, %c
, %[
). En lugar de tomar un argumento char *
, se necesita un argumento char **
, y se asigna el espacio necesario para el valor se lee:
char *buffer = 0;
if (sscanf(data, "%ms", &buffer) == 1)
{
printf("String is: <<%s>>\n", buffer);
free(buffer);
}
Si la función sscanf()
no cumple con todas las especificaciones de conversión, a continuación, toda la memoria se asigna para %ms
, las conversiones similares se liberan antes de que la función regrese.
Entonces, ¿alguien sabe cómo hacer eso con scanf entonces? – goe
Usar fgets en un bucle puede permitirle aceptar cantidades arbitrarias de texto, simplemente mantenga 'realloc()' ing en su búfer. – bdonlan