2
votes

Pourquoi ne puis-je pas utiliser «scanf_s» pour lire un caractère et un nombre à la fois?

Ce code plante:

scanf_s("%c",&ch);
scanf_s("%d",&x);//Run succeed

Mais ce code fonctionne:

scanf_s("%c %d",&ch,&x);//Run error

Je veux savoir pourquoi le premier fragment de code est erroné.

«erreur d'exécution» signifie Le compilateur a un avertissement et quelque chose ne va pas lorsque j'exécute l'entrée du programme


2 commentaires

Qu'est-ce qu'une "erreur d'exécution"?


Voulez-vous dire un avertissement émis par votre compilateur ou quelque chose qui ne va pas une fois que vous exécutez votre programme? Quoi qu'il en soit, veuillez afficher le message correspondant.


3 Réponses :


3
votes

Comme vous utilisez scanf_s (contrairement à scanf ), vous devez fournir un paramètre de longueur supplémentaire pour % c (cf, par exemple, ce document de Microsoft concernant scanf_s ):

Contrairement à scanf et wscanf, scanf_s et wscanf_s vous obligent à spécifier tailles de tampon pour certains paramètres. Spécifiez les tailles pour tous les c, C, s, S ou string control set [] parameters.

Vous devrez donc écrire

scanf_s ("%c %d", &ch, 1, &x);

en indiquant que le premier % c doit lire au plus un caractère. p>

Notez que scanf_s ("% c", & ch); devrait émettre le même avertissement / erreur car il manque également le paramètre de longueur obligatoire pour % c .

La commande scanf_s ("% d", & x); , en revanche, est OK car % d ne nécessite pas (ne doit pas être fourni ) un paramètre de longueur supplémentaire.


1 commentaires

MSVC est désagréable de ne pas utiliser scanf () mais ne vérifie pas les types d'argument pour scanf_s quand c'est facile à faire avec une chaîne de format constant ...



2
votes

Je suppose que vous utilisez MSVC, ce qui donne une erreur si vous utilisez scanf au lieu de scanf_s . Je suppose également que vous souhaitez utiliser le premier et non le second. Pour désactiver l'erreur, allez dans le menu Projet -> Propriétés [Nom du projet] -> C / C ++ -> Préprocesseur. Dans le champ "Définitions du préprocesseur", ajoutez la macro _CRT_SECURE_NO_WARNINGS . Cliquez ensuite sur "Appliquer".

Vous devriez maintenant pouvoir utiliser scanf comme vous le feriez sur n'importe quel autre compilateur / IDE.

 entrez la description de l'image ici


0 commentaires

0
votes

En tant qu'extension de la réponse de Stephan Lechner , considérez ce qui se passe lors de l'exécution de scanf_s ("% c % d ", & ch, & x) .

Techniquement, c'est un comportement indéfini car vous n'avez pas spécifié les bons paramètres pour scanf_s .

Cependant, pratiquement , le code essaiera d'interpréter les valeurs indésirables dans la mémoire comme des paramètres manquants. Autrement dit, le code est équivalent à quelque chose comme ceci:

scanf_s("%c %d", &ch, 0xf0000000, 0xdeadbeef);

Ici 0xf0000000 représente l'adresse de la variable x . Le code de scanf_s l'interprétera comme une taille de tampon (un très grand tampon), mais cela n'a aucun effet car % c lui dit de ne lire qu'un octet. De plus, 0xdeadbeef représente le courrier indésirable, et le code l'interprète comme une adresse pour écrire votre résultat entier. L'écriture à des adresses aléatoires est un grand non-non, donc ça plante.

Lorsque votre code lit le char et le int séparément, il ne se rencontre jamais écrire à une adresse aléatoire, donc tout fonctionne bien, et si vous ignorez les avertissements du compilateur, vous ne savez jamais que votre code est bogué.


0 commentaires