Cómo hacer scanf para un solo carácter en C [duplicate]

5 minutos de lectura

avatar de usuario
Yuval

En C: estoy tratando de obtener caracteres del usuario con scanf y cuando lo ejecuto, el programa no espera a que el usuario escriba nada…

Este es el código:

char ch;
printf("Enter one char");
scanf("%c", &ch);
printf("%c\n",ch);

¿Por qué no funciona?

  • Solo para aclarar aquí, si el programa C contiene solamente el código anterior, funcionará como se esperaba. Los problemas potenciales como el que OP menciona solo surgen cuando se usa junto con otro código de E/S, por las razones mencionadas en la respuesta de PP.

    – formulador

    04/01/2018 a las 11:00


Él %c El especificador de conversión no omitirá automáticamente ningún espacio en blanco inicial, por lo que si hay una nueva línea perdida en el flujo de entrada (de una entrada anterior, por ejemplo), el scanf la llamada lo consumirá inmediatamente.

Una forma de solucionar el problema es poner un espacio en blanco antes del especificador de conversión en la cadena de formato:

scanf(" %c", &c);

El espacio en blanco en la cadena de formato indica scanf para omitir los espacios en blanco iniciales, y el primer carácter que no sea un espacio en blanco se leerá con el %c especificador de conversión.

En primer lugar, evita scanf(). Usarlo no vale la pena.

Ver: ¿Por qué todo el mundo dice que no use scanf? ¿Qué debo usar en su lugar?

Usar un carácter de espacio en blanco en scanf() ignoraría cualquier cantidad de caracteres de espacio en blanco que queden en el flujo de entrada, ¿qué sucede si necesita leer más entradas? Considerar:

#include <stdio.h>

int main(void)
{
   char ch1, ch2;

   scanf("%c", &ch1);  /* Leaves the newline in the input */
   scanf(" %c", &ch2); /* The leading whitespace ensures it's the
                          previous newline is ignored */
   printf("ch1: %c, ch2: %c\n", ch1, ch2);

   /* All good so far */

   char ch3;
   scanf("%c", &ch3); /* Doesn't read input due to the same problem */
   printf("ch3: %c\n", ch3);

   return 0;
}

Mientras que el 3er scanf() se puede arreglar de la misma manera usando un espacio en blanco inicial, no siempre va a ser tan simple como el anterior. Otro gran problema es, scanf() no descartará ninguna entrada en el flujo de entrada si no coincide con el formato. Por ejemplo, si ingresa abc por un int como: scanf("%d", &int_var); entonces abc Habrá que leer y descartar. Considerar:

#include <stdio.h>

int main(void)
{
    int i;

    while(1) {
        if (scanf("%d", &i) != 1) { /* Input "abc" */
            printf("Invalid input. Try again\n");
        } else {
            break;
        }
    }

    printf("Int read: %d\n", i);
    return 0;
}

Otro problema común es mezclar scanf() y fgets(). Considerar:

#include <stdio.h>

int main(void)
{
    int age;
    char name[256];
    printf("Input your age:");
    scanf("%d", &age); /* Input 10 */
    printf("Input your full name [firstname lastname]");
    fgets(name, sizeof name, stdin); /* Doesn't read! */
    return 0;
}

la llamada a fgets() no espera la entrada porque se lee la nueva línea dejada por la llamada scanf() anterior y fgets() finaliza la lectura de entrada cuando encuentra una nueva línea.

Hay muchos otros problemas similares asociados con scanf(). Es por eso que generalmente se recomienda evitarlo.

Entonces, ¿cuál es la alternativa? Usar fgets() funcionan en su lugar de la siguiente manera para leer un solo carácter:

#include <stdio.h>

int main(void)
{
    char line[256];
    char ch;

    if (fgets(line, sizeof line, stdin) == NULL) {
        printf("Input error.\n");
        exit(1);
    }

    ch = line[0];
    printf("Character read: %c\n", ch);
    return 0;
}

Un detalle a tener en cuenta al usar fgets() leerá el carácter de nueva línea si hay suficiente espacio en el búfer de entrada. Si no es deseable, puede eliminarlo:

char line[256];

if (fgets(line, sizeof line, stdin) == NULL) {
    printf("Input error.\n");
    exit(1);
}

line[strcpsn(line, "\n")] = 0; /* removes the trailing newline, if present */

intenta usar getchar(); en cambio

sintaxis:

void main() {
    char ch;
    ch = getchar();
}

avatar de usuario
edmanicom

El único código que funcionó para mí es:

scanf(" %c",&c);

Estaba teniendo el mismo problema, y ​​solo con personajes individuales. Después de una hora de pruebas aleatorias, aún no puedo informar un problema. Uno pensaría que C tendría ahora una función a prueba de balas para recuperar caracteres individuales del teclado, y no una serie de posibles trucos… Solo digo…

Esto funciona para mí, pruébalo

int main(){
char c;
scanf(" %c",&c);
printf("%c",c);
return 0;
}

  • ¡Eso sí que es salvaje! ¿Podría explicar por qué el espacio en frente de %c hace la diferencia?

    –Max Coplan

    10 sep 2019 a las 15:59

  • Resuelto: cheque estos fuera

    –Max Coplan

    10 sep 2019 a las 16:02

  • Esto no parece agregar más información que la respuesta aceptada de 2012.

    – domsson

    6 de enero de 2020 a las 18:05

avatar de usuario
triplicado

Aquí hay algo similar que me gustaría compartir,

mientras trabaja en Visual Studio, podría obtener un error como:

‘scanf’: la función o variable puede no ser segura. Considere usar scanf_s en cambio. Para deshabilitar la obsolescencia, use _CRT_SECURE_NO_WARNINGS

Para evitar esto, debe escribirlo en el siguiente formato

Un solo carácter puede leerse de la siguiente manera:

char c;
scanf_s("%c", &c, 1);

Cuando se leen varios caracteres para cadenas terminadas en un valor no nulo, se utilizan enteros como especificación de ancho y tamaño de búfer.

char c[4];
scanf_s("%4c", &c, _countof(c));

  • ¡Eso sí que es salvaje! ¿Podría explicar por qué el espacio en frente de %c hace la diferencia?

    –Max Coplan

    10 sep 2019 a las 15:59

  • Resuelto: cheque estos fuera

    –Max Coplan

    10 sep 2019 a las 16:02

  • Esto no parece agregar más información que la respuesta aceptada de 2012.

    – domsson

    6 de enero de 2020 a las 18:05

avatar de usuario
Kaushik

ni fgets ni getchar funcionan para resolver el problema. la única solución es dejar un espacio antes de %c al usar scanf scanf(” %c”,ch); // solo funcionará

En los fgets siguientes tampoco funcionan..

char line[256];
char ch;
int i;

printf("Enter a num : ");
scanf("%d",&i);
printf("Enter a char : ");

if (fgets(line, sizeof line, stdin) == NULL) {
    printf("Input error.\n");
    exit(1);
}

ch = line[0];
printf("Character read: %c\n", ch);

¿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