L'avantage de scanf
est une fois que vous apprendrez comment utiliser l'outil, comme vous devriez toujours faire en C, il a usecases extrêmement utile. Vous pouvez apprendre à utiliser scanf
et vos amis en lisant et en comprenant the manual. Si vous ne pouvez pas passer à travers ce manuel sans problèmes de compréhension graves, cela signifierait probablement que vous ne connaissez pas très bien C.
scanf
et les amis ont souffert des choix de conception malheureux qui a rendu difficile (et parfois impossible) d'utiliser correctement sans lire la documentation, comme les autres réponses ont montré. Cela se produit tout au long de C, malheureusement, donc si je devais déconseiller d'utiliser scanf
alors je déconseillerais probablement d'utiliser C.
L'un des plus grands inconvénients semble être purement la réputation qu'il gagne parmi les non-initiés; Comme avec de nombreuses fonctionnalités utiles de C, nous devrions être bien informés avant de l'utiliser. La clé est de réaliser que, comme pour le reste de C, il semble succinct et idiomatique, mais cela peut être subtilement trompeur. Ceci est omniprésent en C; il est facile pour les débutants d'écrire un code qu'ils pensent logique et qui pourrait même fonctionner pour eux au début, mais cela n'a aucun sens et peut échouer de manière catastrophique.
Par exemple, les non-initiés attendent généralement que le délégué %s
causerait une ligne à lire, et tout cela peut sembler intuitive, il est pas nécessairement vrai. Il est plus approprié de décrire le champ lu comme un mot. La lecture du manuel est fortement conseillée pour chaque fonction.
Quelle serait la réponse à cette question sans mentionner son manque de sécurité et le risque de débordement de la mémoire tampon? Comme nous l'avons déjà mentionné, C n'est pas un langage sûr et nous permettra de couper les coins, éventuellement d'appliquer une optimisation au détriment de l'exactitude ou plus probablement parce que nous sommes des programmeurs paresseux. Ainsi, quand nous savons que le système ne recevra jamais une chaîne plus grande qu'un nombre fixe d'octets, nous avons la possibilité de déclarer un tableau de cette taille et de renoncer à la vérification des limites. Je ne vois pas vraiment cela comme une chute; c'est une option. Encore une fois, la lecture du manuel est fortement conseillée et nous révélerait cette option.
Les programmeurs paresseux ne sont pas les seuls piqués par scanf
. Il n'est pas rare de voir des gens essayer de lire les valeurs float
ou double
en utilisant %d
, par exemple. Ils ont généralement tort de croire que la mise en œuvre effectuera une sorte de conversion en coulisse, ce qui serait logique car des conversions similaires se produisent dans le reste de la langue, mais ce n'est pas le cas ici. Comme je l'ai dit plus tôt, scanf
et amis (et en effet le reste de C) sont trompeuses; ils semblent succincts et idiomatiques mais ils ne le sont pas.
Les programmeurs inexpérimentés ne sont pas obligés de considérer le succès de l'opération. Supposons que l'utilisateur entre quelque chose de complètement non numérique quand nous avons dit scanf
pour lire et convertir une séquence de chiffres décimaux en utilisant %d
. La seule façon d'intercepter de telles données erronées est de vérifier la valeur de retour, et à quelle fréquence est-ce que nous prenons la peine de vérifier la valeur de retour? Tout comme fgets
, lorsque scanf
et les amis ne lisent pas ce qu'ils sont censés lire, le flux restera dans un état inhabituel; - Dans le cas de fgets
, s'il n'y a pas suffisamment d'espace pour stocker une ligne complète, le reste de la ligne non lue pourrait être traité de manière erronée comme s'il s'agissait d'une nouvelle ligne alors qu'elle ne l'est pas. - Dans le cas de scanf
et des amis, une conversion a échoué comme indiqué ci-dessus, les données erronées ne sont pas lues dans le flux et peuvent être traitées de manière erronée comme si elles faisaient partie d'un champ différent.
Il n'est pas plus facile d'utiliser scanf
que d'utiliser fgets
.Si nous vérifions le succès en recherchant un '\n'
lorsque nous utilisons fgets
ou en inspectant la valeur de retour lorsque nous utilisons scanf
et amis, et nous constatons que nous avons lu une ligne incomplète en utilisant fgets
ou échoué à lire un champ en utilisant scanf
, alors nous sommes confrontés à la même réalité: nous sommes susceptibles de ignorer l'entrée (généralement jusqu'à et y compris la nouvelle ligne suivante)! Yuuuuuuck!
Malheureusement, scanf
rend simultanément difficile (non intuitif) et facile (le moins grand nombre de frappes) d'ignorer les entrées de cette manière. Face à cette réalité d'abandon de l'entrée utilisateur, certains ont essayé
scanf("%*[^\n]%*c");
, sans se rendre compte que le délégué %*[^\n]
échouera lorsqu'il ne rencontrera rien d'autre qu'un saut de ligne, et donc le retour à la ligne sera toujours laissé sur le flux.
Une légère adaptation, en séparant les deux délégués de format et nous voyons un certain succès ici: scanf("%*[^\n]"); getchar();
. Essayez de le faire avec si peu de frappes en utilisant un autre outil;)
Voir aussi [Un guide du débutant loin de 'scanf()'] (http://sekrit.de/webdocs/c/beginners-guide-away- from-scanf.html). –