128 votes

Comment faire un scanf pour un seul caractère en C ?

En C : J'essaie d'obtenir le caractère de l'utilisateur avec scanf et quand je l'exécute, le programme n'attend pas que l'utilisateur tape quoi que ce soit...

Voici le code :

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

Pourquoi ne fonctionne-t-il pas ?

288voto

John Bode Points 33046

El %c ne sautera pas automatiquement les espaces en début de ligne, donc s'il y a un saut de ligne dans le flux d'entrée (d'une entrée précédente, par exemple), l'indicateur de conversion scanf l'appel le consommera immédiatement.

Une façon de contourner le problème est de placer un espace blanc avant le spécificateur de conversion dans la chaîne de format :

scanf(" %c", &c);

Le blanc dans la chaîne de format indique scanf pour ignorer les espaces blancs de tête, et le premier caractère qui n'est pas un espace blanc sera lu avec la fonction %c spécificateur de conversion.

32voto

KingsIndian Points 26855

Tout d'abord, évitez scanf() . L'utiliser ne vaut pas la peine de souffrir.

Voir : Pourquoi tout le monde dit qu'il ne faut pas utiliser scanf ? Que dois-je utiliser à la place ?

L'utilisation d'un caractère d'espacement dans scanf() ignorerait le nombre de caractères d'espacement restant dans le flux d'entrée, mais que faire si vous avez besoin de lire plus d'entrées ? Pensez-y :

#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;
}

Si le troisième scanf() peut être corrigé de la même manière en utilisant un espace en tête, ce n'est pas toujours aussi simple que cela. Un autre problème majeur est, scanf() ne rejettera aucune entrée dans le flux d'entrée si elle ne correspond pas au format. Par exemple, si vous entrez abc pour un int comme : scanf("%d", &int_var); puis abc devra être lu et jeté. Réfléchissez :

#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;
}

Un autre problème courant est le mélange scanf() y fgets() . Considérez :

#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;
}

L'appel à fgets() n'attend pas l'entrée car la nouvelle ligne laissée par l'appel scanf() précédent est lue et fgets() termine la lecture de l'entrée lorsqu'il rencontre une nouvelle ligne.

Il y a beaucoup d'autres problèmes similaires associés à scanf() . C'est pourquoi il est généralement recommandé de l'éviter.

Alors, quelle est l'alternative ? Utiliser fgets() de la manière suivante pour lire un seul caractère :

#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 détail à prendre en compte lors de l'utilisation de fgets() lira le caractère de nouvelle ligne s'il y a assez de place dans le tampon inut. Si ce n'est pas souhaitable, vous pouvez le supprimer :

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 */

9voto

Praveen samuel Points 99

Cela fonctionne pour moi, essayez-le

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

5voto

Sanberk Points 51

Voici une chose similaire que j'aimerais partager,

pendant que vous travaillez sur Visual Studio, vous pouvez obtenir une erreur comme :

'scanf' : la fonction ou la variable n'est peut-être pas sûre. Envisagez d'utiliser scanf_s à la place. Pour désactiver la dépréciation, utilisez _CRT_SECURE_NO_WARNINGS

Pour éviter cela, vous devez l'écrire dans le format suivant

Un seul caractère peut être lu comme suit :

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

Lorsque des caractères multiples sont lus pour des chaînes de caractères dont la terminaison n'est pas nulle, des nombres entiers sont utilisés pour spécifier la largeur et la taille du tampon.

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

3voto

CoderTag Points 33

Ni fgets ni getchar ne fonctionnent pour résoudre le problème. la seule solution est de garder un espace avant %c en utilisant scanf scanf(" %c",ch) ; // ne fonctionnera qu'une fois

Dans le fgets suivant ne fonctionne pas non plus

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);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X