¿Cómo permite que se ingresen espacios usando scanf?

6 minutos de lectura

avatar de usuario
Kredns

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. como hago scanf() permitir espacios

  • Tenga en cuenta que más idiomático es ‘malloc(sizeof(char) * 256 + 1)’, o ‘malloc(256 + 1)’, o incluso mejor (asumiendo que ‘name’ se usará estrictamente localmente) ‘char name[256+1]’. El ‘+1’ puede actuar como un mnemotécnico para el terminador nulo, que debe incluirse en la asignación.

    –Barry Kelly

    8 de agosto de 2009 a las 4:47

  • @Barry – Sospecho sizeof(char) + 256 fue un error tipográfico.

    – Chris Lutz

    20 de julio de 2011 a las 22:06

avatar de usuario
SVA

Este ejemplo utiliza un scanset invertido, por lo que scanf sigue tomando valores hasta que encuentra un ‘\n’– nueva línea, por lo que también se guardan espacios.

#include <stdio.h>

int main (int argc, char const *argv[])
{
    char name[20];

    // get up to buffer size - 1 characters (to account for NULL terminator)
    scanf("%19[^\n]", name);
    printf("%s\n", name);
    return 0;
}

  • Cuidado con los desbordamientos de búfer. Si el usuario escribe un “nombre” con 50 caracteres, el programa probablemente fallará.

    – brunoais

    29 de enero de 2013 a las 15:17

  • Como sabe el tamaño del búfer, puede usar %20[^\n]s para evitar desbordamientos de búfer

    – osvein

    11/11/2017 a las 20:52

  • 45 puntos y nadie señaló el evidente culto de carga de tener s ¡allí!

    – Antti Haapala — Слава Україні

    27 de junio de 2019 a las 5:39

  • no sabía sobre fgets(). En realidad parece más fácil de usar entonces scanf(). +1

    – Kredns

    8 de agosto de 2009 a las 6:37

  • Si solo desea obtener una línea del usuario, es más fácil. También es más seguro ya que puede evitar desbordamientos de búfer. La familia scanf es realmente útil para convertir una cadena en cosas diferentes (como cuatro caracteres y un int, por ejemplo, con “%c%c%c%c%d”) pero, incluso entonces, debería usar fgets y sscanf, no scanf, para evitar la posibilidad de desbordamiento del búfer.

    – pax diablo

    8 de agosto de 2009 a las 6:48

  • Puede poner el tamaño máximo del búfer en formato scanf, simplemente no puede poner el tiempo de ejecución calculado sin construir el formato en tiempo de ejecución (no existe el equivalente de * para printf, * es un modificador válido para scanf con otro comportamiento: suprimir la asignación ).

    – Un programador

    8 de agosto de 2009 a las 11:55

  • @JonathanKomar y cualquier otra persona que lea esto en el futuro: si tu profesor te dijera que tienes que usar scanf en una tarea, se equivocaron al hacerlo, y puedes decirles que lo dije, y si quieren discutir conmigo al respecto, mi dirección de correo electrónico se encuentra fácilmente en mi perfil.

    – zwol

    30 de abril de 2019 a las 18:10

  • @Rainning: no está destinado a ser hermoso, de lo contrario no tendríamos strcscnp o atoi. Es un nombre funcional probablemente destinado a indicar gets desde un identificador de archivo. Su capacidad para hacer lo que quería el OP no se ve afectada de ninguna manera por su nombre.

    – pax diablo

    14 de marzo a las 10:04


avatar de usuario
Vitim.es

Puedes usar esto

char name[20];
scanf("%20[^\n]", name);

O esto

void getText(char *message, char *variable, int size){
    printf("\n %s: ", message);
    fgets(variable, sizeof(char) * size, stdin);
    sscanf(variable, "%[^\n]", variable);
}

char name[20];
getText("Your name", name, 20);

MANIFESTACIÓN

  • No probé, pero según otras respuestas en esta misma página, creo que el tamaño de búfer correcto para scanf en su ejemplo sería: scanf("%19[^\n]", name); (todavía +1 para la respuesta concisa)

    – DrBeco

    12 de junio de 2015 a las 1:12


  • Solo como una nota al margen, sizeof(char) es por definición siempre 1, por lo que no hay necesidad de multiplicar por él.

    – pax diablo

    22 de marzo de 2016 a las 7:37

  • @paxdiablo No creo que esto sea cierto para todas las arquitecturas/plataformas

    – Vitim.es

    27 de febrero de 2021 a las 23:50

  • @Vitim.us: si te refieres a mi sizeof(char) == 1 comentario, es obligatorio por el estándar. Véase, por ejemplo, C11 6.5.3.4 /4: “Cuando sizeof se aplica a un operando que tiene tipo char, unsigned charo signed char(o una versión calificada del mismo) el resultado es 1“. Algunas personas cometen el error de que, desde sizeof devuelve el número de bytes en un tipo/variable, un 16 bits char dará dos. Pero ese no es el caso, ya que el estándar no define “byte” como ocho bits, sino que lo define como “una secuencia contigua de bits, cuyo número está definido por la implementación”.

    – pax diablo

    28 de febrero de 2021 a las 1:26


getline()

Ahora parte de POSIX, sin embargo.

También soluciona el problema de asignación de búfer sobre el que preguntó anteriormente, aunque debe solucionarlo. freeing la memoria.

  • No probé, pero según otras respuestas en esta misma página, creo que el tamaño de búfer correcto para scanf en su ejemplo sería: scanf("%19[^\n]", name); (todavía +1 para la respuesta concisa)

    – DrBeco

    12 de junio de 2015 a las 1:12


  • Solo como una nota al margen, sizeof(char) es por definición siempre 1, por lo que no hay necesidad de multiplicar por él.

    – pax diablo

    22 de marzo de 2016 a las 7:37

  • @paxdiablo No creo que esto sea cierto para todas las arquitecturas/plataformas

    – Vitim.es

    27 de febrero de 2021 a las 23:50

  • @Vitim.us: si te refieres a mi sizeof(char) == 1 comentario, es obligatorio por el estándar. Véase, por ejemplo, C11 6.5.3.4 /4: “Cuando sizeof se aplica a un operando que tiene tipo char, unsigned charo signed char(o una versión calificada del mismo) el resultado es 1“. Algunas personas cometen el error de que, desde sizeof devuelve el número de bytes en un tipo/variable, un 16 bits char dará dos. Pero ese no es el caso, ya que el estándar no define “byte” como ocho bits, sino que lo define como “una secuencia contigua de bits, cuyo número está definido por la implementación”.

    – pax diablo

    28 de febrero de 2021 a las 1:26


avatar de usuario
Cristóbal

no usar scanf() para leer cadenas sin especificar un ancho de campo. También debe verificar los valores devueltos en busca de errores:

#include <stdio.h>

#define NAME_MAX    80
#define NAME_MAX_S "80"

int main(void)
{
    static char name[NAME_MAX + 1]; // + 1 because of null
    if(scanf("%" NAME_MAX_S "[^\n]", name) != 1)
    {
        fputs("io error or premature end of line\n", stderr);
        return 1;
    }

    printf("Hello %s. Nice to meet you.\n", name);
}

Alternativamente, utilice fgets():

#include <stdio.h>

#define NAME_MAX 80

int main(void)
{
    static char name[NAME_MAX + 2]; // + 2 because of newline and null
    if(!fgets(name, sizeof(name), stdin))
    {
        fputs("io error\n", stderr);
        return 1;
    }

    // don't print newline
    printf("Hello %.*s. Nice to meet you.\n", strlen(name) - 1, name);
}

¿Ha sido útil esta solución?