Comment utiliser sscanf correctement et en toute sécurité
Tout d'abord, d'autres questions sur l'utilisation de sscanf
ne réponds pas à ma question parce que la réponse commune est de ne pas utiliser sscanf
à tous et à l'utilisation fgets
ou getch
au lieu de cela, ce qui est impossible dans mon cas.
Le problème, c'est mon C professeur veut que j'utilise scanf
dans un programme. C'est une exigence.
Toutefois, le programme doit également gérer toutes les entrée incorrecte.
Le programme doit lire un tableau d'entiers. Il n'a pas d'importance dans ce format les entiers
pour le tableau sont fournis. Pour rendre la tâche plus facile, le programme peut lire d'abord la taille de la matrice, puis les nombres entiers de chaque dans une nouvelle ligne.
Le programme doit gérer les entrées comme ceux-ci (et rapport d'erreurs de manière appropriée):
- 999999999999999...9 (nombres supérieurs entier)
- 12a3 (ne pas lire ce que d'un nombre entier 12)
- a...z (chaînes de caractères)
- 11 aa 22 33\n dans une seule ligne (ce qui peut être gérée par jeter tout ce qui est après 11)
- entrées plus grand que le tableau d'entrée
Il y a peut être plus mauvaise des cas, ce sont les seuls peu de ce que je pouvais penser.
Si l'erreur de saisie est fourni, le programme doit demander à l'utilisateur de saisir à nouveau jusqu'à ce
l'entrée correcte est donnée, mais la précédente entrée correcte doit être tenu (seulement incorrect
d'entrée doit être désactivée à partir du flux d'entrée).
Tout doit être conforme à la norme C99.
OriginalL'auteur evodevo | 2012-02-26
Vous devez vous connecter pour publier un commentaire.
La
scanf
famille de fonction ne peuvent pas être utilisés en toute sécurité, en particulier lorsque vous traitez avec des entiers. Le premier cas que vous avez mentionné est particulièrement gênant. La norme dit ceci:Pure et simple. Vous pourriez penser de
%5d
trucs et que telle, mais vous trouverez qu'ils ne sont pas fiables. Ou peut-être quelqu'un va penser de errno. Lescanf
fonctions n'est pas nécessaire de définirerrno
.Suivre cette peu de fun page: ils finissent par amerrissage forcé
scanf
tout à fait.Afin de revenir à votre C professeur et demandez-leur: comment fonctionne exactement la C99 mandat que sscanf signalent des erreurs ?
OriginalL'auteur cnicutar
Eh bien, laissez-sscanf accepter toutes les entrées que %s (c'est à dire des chaînes de caractères), puis le programme de les analyser
%s
dansscanf
=== potentiel de dépassement de la mémoire tampon.Oui, mais pas forcément dans
sscanf
, tant que la destination est plus grand que la source. D'autre part,%s
vous donne les espaces délimités par des mots, et non pas l'ensemble de la chaîne.À l'aide d'une largeur de champ comme "%100s" (ex: 100 limite caractères) peut être utilisé pour éviter les débordements.
Si un numéro de 100 zéros (par ex. "000000000.....0001") être géré correctement?
dans la demande du commettant, oui, "manipulé correctement" signifie ici une erreur doit être produit, ou si les conditions qui permettent à ces numéros (pas clair), la valeur doit être accepté. Pour utiliser cette réponse de l'approche sans dépassement de tampon, un domaine limite de largeur doit être utilisé. Pour toutes les entrées qui dépassent la taille de la mémoire tampon d'entrée doit être jetée jusqu'à la prochaine ligne. Si les conditions le permettent, les entrées de tous les zéros (éventuellement avec un signe -) a pu être détecté et accepté.
OriginalL'auteur mikithskegg
Si vous devez utiliser
scanf
pour accepter l'entrée, je pense que vous commencez avec quelque chose d'un peu semblable à la suivante.Ce sera la poignée (plus ou moins) le format libre entrée de problème depuis
scanf
sauterez automatiquement principaux espaces lors de l'appariement d'un%d
format.L'observation essentielle pour de nombreuses le reste de vos préoccupations, c'est que
scanf
vous indique le nombre de codes de format il correctement analysées. Donc,Je pense que cela gère directement les préoccupations (3) et (4)
Par lui-même, ce n'est pas tout à fait traiter le cas de l'entrée
12a3
. La première fois dans la boucle,scanf
serait parse '12as an integer 12, leaving the remaining
a3" pour la prochaine boucle. Vous obtiendrez une erreur à la prochaine ronde, si. Est-ce suffisant pour votre professeur?Pour des entiers plus grands que exemple maxint, par exemple, "999999.......999", je ne suis pas sûr de ce que vous pouvez faire avec droit
scanf
.Pour entrées plus grand que le tableau d'entrée, ce n'est pas un
scanf
problème soi. Vous avez juste besoin de compter le nombre d'entiers que vous avez analysé jusqu'à présent.Si vous êtes autorisé à l'utiliser
sscanf
pour décoder les chaînes après qu'ils ont été extraites à partir du flux d'entrée par quelque chose commescanf("%s")
vous pouvez aussi faire quelque chose comme ceci:Cela fonctionne pour n'importe quelle séquence de blanc-espace des mots séparés, et vous permet de séparer la numérisation de l'entrée pour les mots, et puis de voir si ces mots ressemblent à des numéros ou non. Et, si vous avez, vous pouvez utiliser
scanf
variantes pour chaque partie.Vrai, mais
scanf("%c", &c)
est un moyen coûteux d'émulergetchar()
. La cession vraiment cette sorte de trivial syntaxique utilisation descanf
? Je pense que @cnicutar commentaire vraiment les ongles d'une question centrale: compte tenu de la cité extrait de la norme, il est impossible d'utiliserscanf
en toute sécurité pour analyser débordement d'entier entrées.c) est un bon exemple de pourquoi les chaînes de format devrait, en général, être évitée en C++. Dommage que l'on ne peut pas signet commentaires 😀
OriginalL'auteur Dale Hagglund