¿Por qué scanf solicita dos veces la entrada cuando hay una nueva línea al final de la cadena de formato?

5 minutos de lectura

avatar de usuario
alegría

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *method1(void)
{
    static char a[4];
    scanf("%s\n", a);
    return a;
}

int main(void)
{
    char *h = method1();
    printf("%s\n", h);
    return 0;
}

Cuando ejecuto el código anterior, el mensaje me pregunta dos veces para la entrada (solo uso scanf una vez en el código). ¿Porqué es eso?

(Ingresé ‘jo’; me pidió más información, así que ingresé ‘jo’ nuevamente. Luego solo imprimió ‘jo’ una vez).

  • ¿Qué salida obtuviste?

    – Aswin Mu ru gesh

    1 de abril de 2013 a las 8:23

  • Esa es una matriz muy corta. ¿Introdujo demasiados datos?

    –Jonathan Leffler

    1 de abril de 2013 a las 8:24

  • Entro jo. pide otra entrada. luego entro en jo de nuevo. entonces solo imprime jo una vez.

    – alegría

    1 de abril de 2013 a las 8:25


  • Sé que es solo un fragmento, pero deberías siempre verifique el resultado de las funciones de conversión como scanf y amigos.

    – Jens

    01/04/2013 a las 19:50

avatar de usuario
MOHAMED

tienes que quitar el \n del formato de cadena del scanf. Debería ser

scanf("%s",a);

EDITAR: Explicación

la %s significa que scanf lee el carácter de entrada hasta que obtiene un delimitador que debería ser un espacio en blanco como un espacio, una pestaña o una nueva línea (\n) por lo que la primera entrada se obtiene como delimitador para el "%s" y agregando el "\n" al formato de cadena "%s\n" significa que el scanf esperará 2 líneas nuevas, la primera línea nueva está relacionada con el delimitador de la "%s" y la segunda nueva línea está relacionada con el\n del formato de cadena.

  • Estás en el camino correcto, pero no lo has dicho. scanf seguirá leyendo espacios en blanco hasta que encuentre un carácter que no sea un espacio. Puede ingresar muchas líneas nuevas (y espacios en blanco o tabuladores) antes de que se ingrese un espacio y se detenga scanf. Una razón más para preferir fgets() y sscanf() sobre las variantes de E/S de archivo de scanf().

    –Jonathan Leffler

    1 de abril de 2013 a las 8:41

  • Su razonamiento sobre scanf esperando dos nuevas líneas es incorrecto. Todas las nuevas líneas ingresadas (incluso más de dos) son escaneadas por el soltero \n en el formato, al igual que los espacios y tabulaciones entremezclados. Lea la especificación scanf en el estándar C o en la página del manual.

    – Jens

    01/04/2013 a las 22:06

avatar de usuario
Jens

Desde mi página de manual de scanf

Los espacios en blanco (como espacios en blanco, tabuladores o saltos de línea) en la cadena de formato coinciden con cualquier cantidad de espacio en blanco, incluido ninguno, en la entrada. Todo lo demás coincide solo consigo mismo.

Así con scanf ("%s\n", a) buscará una cadena seguida de un espacio en blanco opcional. Dado que después de la primera línea nueva pueden seguir más espacios en blanco, scanf no se realiza después de la primera línea nueva y busca lo que sigue. Notará que puede ingresar cualquier número de nuevas líneas (o tabulaciones o espacios) y scanf todavía esperará por más.

Sin embargo, cuando ingresa la segunda cadena, la secuencia de espacios en blanco se delimita y el escaneo se detiene.

Usar scanf ("%s", a) para no escanear los espacios en blanco finales.

use gets() o fgets() en su lugar… alternativamente use scanf(“%[^\n]s”,a);

  • scanf entradas en la matriz hasta que reciba un espacio … así que use%[^\n]s… o no use scanf, en su lugar vaya a fgets() o gets()

    – Darshan Shah

    1 de abril de 2013 a las 8:26


  • "%[^\n]s" se compone de dos directivas: %[^\n]que coincide (y almacena) uno o más caracteres que no son ‘\n’, o falla porque encontró un ‘\n’ inmediatamente, y s que coincide con una ‘s’ literal y la descarta, o falla y vuelve a colocar el carácter que no es ‘s’ en la entrada estándar. La primera directiva fallará en los intentos consecutivos, porque ‘\n’ no es ‘s’, por lo que ‘\n’ volverá directamente a la entrada estándar y ese será el primer carácter que se encuentre. Ver por ti mismo: char a[64]; int n = scanf("%[^\n]s", a); assert(n == 1); n = scanf("%[^\n]s", a); assert(n == 1);

    – autista

    1 de abril de 2013 a las 9:09


  • Mi sugerencia es leer el fscanf manual para que pueda aclarar la confusión que tiene con respecto a la %[ directive and the %s directive.

    – autistic

    Apr 1, 2013 at 9:11

user avatar
kiranmai

Remove \n from the scanf format and give an input and it displays the output based on the given output once.

Don’t use the escape sequence in scanf stdio function

     scanf ("%s", a);

  • There’s no explanation of why — and what happens when you do. This adds nothing to the answer by MOHAMED, or the accepted answer.

    – Jonathan Leffler

    Jan 17, 2017 at 20:11

user avatar
Srinivas Nallapu

you can use either of these to avoid the mentioned problem :
scanf("%s",a);
or
scanf("\n%s",a);

  • There’s no explanation of why — and what happens when you do. This adds nothing to the answer by MOHAMED, or the accepted answer.

    – Jonathan Leffler

    Jan 17, 2017 at 20:11

user avatar
Ramesh

Try this: Don’t use \n on scanf, it won’t ask you twice and sometimes it might show an error

Your code: scanf("%s\n", a);

Try this on scanf: scanf("%s", a);

  • The other answers stated this 8 years ago. This adds nothing new.

    – Blastfurnace

    Feb 20, 2021 at 18:23

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad