Bonsoir, dans les archives du tuto C à l'époque du sdz, j'aurais une question quand à ce code-ci :
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int choixMenu;
printf("=== Menu ===\n\n");
printf("1. Royal Cheese\n");
printf("2. Mc Deluxe\n");
printf("3. Mc Bacon\n");
printf("4. Big Mac\n");
printf("\nVotre choix ? ");
scanf("%d", &choixMenu);
printf("\n");
switch (choixMenu)
{
case 1:
printf("Vous avez choisi le Royal Cheese. Bon choix !");
break;
case 2:
printf("Vous avez choisi le Mc Deluxe. Berk, trop de sauce...");
break;
case 3:
printf("Vous avez choisi le Mc Bacon. Bon, ca passe encore ca ;o)");
break;
case 4:
printf("Vous avez choisi le Big Mac. Vous devez avoir tres faim !");
break;
default:
printf("Vous n'avez pas rentre un nombre correct. Vous ne mangerez rien du tout !");
break;
}
printf("\n\n");
return 0;
}
Si l'utilisateur entre une chaîne de caractère au lieu d'un nombre, choixMenu peut très bien (même si très peu probable) valoir 1, 2, 3 ou 4 non ?
Dans ce cas, la sortie serait incorrecte, ne vaudrait-il pas mieux tester la valeur de retour de scanf avant le switch pour vérifier si l'entrée est un nombre ?
Oui, je sais qu'en initialisant manuellement avec 0 ou 123 par exemple c'est bon, mais dans ce code-là choixMenu n'est pas initialisé, donc sa valeur est aléatoire non ?
Oui, je sais qu'en initialisant manuellement avec 0 ou 123 par exemple c'est bon, mais dans ce code-là choixMenu n'est pas initialisé, donc sa valeur est aléatoire non ?
Oui et tenter d'y lire une valeur plus loin est un undefined behavior.
Si la saisie n'est pas numérique, le scanf() échoue et l'entier est inchangé. Le prochain scanf() pourra lire le texte si "%s" "%c" ou "%[]", mais veut aussi lire un numérique, le codera continuera jusqu'au prochain scanf() texte. Autrement dit : on ne peut pas utiliser scanf() de manière saine si l'opérateur n'entre pas ce que l'on attend de lui!
Si une variable n'est pas initialisée, effectivement sa valeur est "aléatoire" (En fait, elle contient ce que la mémoire qui lui est réservé contenait avant sa réservation).
Chi_Iroh a écrit:
Dans ce cas, la sortie serait incorrecte, ne vaudrait-il pas mieux tester la valeur de retour de scanf avant le switch pour vérifier si l'entrée est un nombre ?
Ou tu pourrais lire le texte avec fgets() et valider si la chaîne est bien composée de chiffres. Et tu as différents moyens de convertir en nombre.
#include <stdio.h> #include <string.h> int main(void){ char entree[100]; fgets(entree, 100, stdin); printf("%s", entree); char *endl = strchr(entree, '\n'); if(endl) *endl = '\0'; // Je vérifie que ce ne sont que des chiffres. int nombre; sscanf(entree, "%d", &nombre); printf("%d\n", nombre); } Je pense que pour avoir le nombre 1 en tapant un "caractère", il faut taper Control+A
Je pense que le std::cin de C++ te causerait le même problème.
Et c'est plus catastrophique en Python ...
- Edité par PierrotLeFou 4 avril 2022 à 4:09:06
Le Tout est souvent plus grand que la somme de ses parties.
Concernant scanf, c'est fait pour lire de l'entrée correctement formatée, pas celle de l'utilisateur. Le seul moyen de lire « correctement » c'est de lire une ligne entière (avec fgets) et de l'analyser (quand on souhaite lire ligne par ligne, usuellement ce qu'on fait avec des prompts en terminal).
- Edité par markand 4 avril 2022 à 8:44:47
git is great because Linus did it, mercurial is better because he didn't.
Le scanf, c'est pour soi. Si tu te fais un petit truc vite fait avec lequel tu ne joueras pas au con. Si l'utilisateur est tierce, il faut toujours partir de l'idée que ce sera un crétin fini et qu'il répondra 4587.325 quand on lui demandera son plat favori et "Lune" à "10-5 = ?".
Si l'utilisateur est tierce, il faut toujours partir de l'idée que ce sera un crétin fini et qu'il répondra 4587.325 quand on lui demandera son plat favori
Avec fgets, il peux aussi répondre cela !
drx a écrit:
"Lune" à "10-5 = ?".
idem !
scanf est aussi capable de gérer ces cas, avec du code en aval.
Ou il faut être attentif avec scanf, c'est pour les chaînes de caractère, à ne pas aller écrire en dehors du tableau de char qui réceptionne les caractères. Dans ce cas on peux effectivement privilégier fgets, mais il faut savoir que scanf est aussi capable de limiter le nombre de caractère qui seront mis dans le tableau de réception.
...
Validité des entrées avec scanf
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Liens utiles pour le C++
Liens utiles pour le C++
En recherche d'emploi.
Le Tout est souvent plus grand que la somme de ses parties.
git is great because Linus did it, mercurial is better because he didn't.
Bonhomme !! | Jeu de plateforme : Prototype.