Usando el siguiente código:
char *name = malloc(sizeof(char) + 256);
printf("What is your name? ");
scanf("%s", name);
printf("Hello %s. Nice to meet you.\n", name);
Un usuario puede ingresar su nombre, pero cuando ingresa un nombre con un espacio como Lucas Aardvark
, scanf()
simplemente corta todo después Lucas
. ¿Cómo hago para scanf()
permitir espacios?
sizeof(char) + 256
fue un error tipográfico.Respuestas:
Las personas (y especialmente los principiantes) nunca deben usar
scanf("%s")
ogets()
cualquier otra función que no tenga protección de desbordamiento de búfer, a menos que sepa con certeza que la entrada siempre tendrá un formato específico (y tal vez ni siquiera entonces).Recuerde que
scanf
significa "escaneo formateado" y hay un poco menos formateado que los datos ingresados por el usuario. Es ideal si tiene un control total del formato de datos de entrada, pero generalmente no es adecuado para la entrada del usuario.Use
fgets()
(que tiene protección de desbordamiento de búfer) para obtener su entrada en una cadena ysscanf()
evaluarla. Dado que solo desea lo que el usuario ingresó sin analizar, desscanf()
todos modos no necesita en este caso:fuente
fgets()
. En realidad, parece más fácil de usar entoncesscanf()
. +1scanf
tiene un comportamiento indefinido si la conversión numérica se desborda ( N1570 7.21.6.2p10 , última oración, redacción sin cambios desde C89), lo que significa que ninguna de lasscanf
funciones puede usarse de manera segura para la conversión numérica de entradas no confiables.scanf
en una tarea, se equivocaron al hacerlo, y puede decirles que lo dije, y si quieren discutir conmigo al respecto , mi dirección de correo electrónico se encuentra fácilmente desde mi perfil.Tratar
Espero que ayude.
fuente
s
del final de la cadena de entrada, ya que es a la vez superfluo e incorrecto en ciertos casos (como se señaló en comentarios anteriores).[
es su propio especificador de formato en lugar de alguna variación dels
mismo.Este ejemplo utiliza un conjunto de escaneo invertido, por lo que scanf sigue tomando valores hasta que encuentra un '\ n' - nueva línea, para que los espacios también se guarden
fuente
%20[^\n]s
para evitar el desbordamiento del búfers
allí!Puedes usar esto
O esto
MANIFESTACIÓN
fuente
scanf("%19[^\n]", name);
(todavía +1 para la respuesta concisa)sizeof(char)
es por definición siempre 1, por lo que no hay necesidad de multiplicarlo.No lo use
scanf()
para leer cadenas sin especificar un ancho de campo. También debe verificar los valores de retorno para errores:Alternativamente, use
fgets()
:fuente
Puede usar la
fgets()
función para leer una cadena o usarlascanf("%[^\n]s",name);
para que la lectura de la cadena termine al encontrar un carácter de nueva línea.fuente
s
no pertenece allígetline()
Ahora parte de POSIX, no obstante.
También se ocupa del problema de asignación de búfer sobre el que preguntó anteriormente, aunque debe ocuparse de
free
la memoria.fuente
Si alguien todavía está buscando, esto es lo que funcionó para mí: leer una longitud arbitraria de cadena que incluye espacios.
Gracias a muchos carteles en la web por compartir esta solución simple y elegante. Si funciona, el crédito recae en ellos, pero cualquier error es mío.
fuente
errno
y limpiar la memoria asignada.s
no pertenece allí después del scansetPuede utilizar
scanf
para este propósito con un pequeño truco. En realidad, debe permitir la entrada del usuario hasta que el usuario presione Enter (\n
). Esto considerará todos los personajes, incluido el espacio . Aquí hay un ejemplo:¿Cómo funciona esto? Cuando el usuario ingresa caracteres de la entrada estándar, se almacenarán en una variable de cadena hasta el primer espacio en blanco. Después de eso, el resto de la entrada permanecerá en la secuencia de entrada y esperará el próximo scanf. A continuación, tenemos un
for
bucle que toma char por char del flujo de entrada (till\n
) y los une al final de la variable de cadena , formando así una cadena completa igual que la entrada del usuario desde el teclado.¡Espero que esto ayude a alguien!
fuente
Si bien no deberías usarlo
scanf()
para este tipo de cosas, porque hay llamadas mucho mejores comogets()
ogetline()
, se puede hacer:fuente
gets
fue desaprobado y eliminado ( stackoverflow.com/questions/30890696/why-gets-is-deprecated ) del estándar. Es incluso peor quescanf
porque al menos el último tiene maneras de hacer más segura.fuente
s
no pertenece allí después del scanset