C'est souvent discuté, plein d'avis, mais intéressant néanmoins. J'ai observé qu'une grande majorité de ceux qui ont déjà répondu à des questions similaires sur ce site tomber sur le côté de fgets()
. Je suis l'un d'entre eux. Je trouve fgets()
être beaucoup mieux d'utiliser pour la saisie de l'utilisateur de scanf()
à quelques exceptions près. scanf()
est considéré par beaucoup comme sous-optimale de la méthode pour la manipulation de la saisie de l'utilisateur. Par exemple
"...il vous dira s'il a réussi ou échoué, mais peut vous dire seulement approximativement à l'endroit où il a échoué, et pas du tout comment ou pourquoi. Vous
ont très peu l'occasion de faire de récupération des erreurs."
(jamesdlin). Mais dans l'intérêt de tenter de l'équilibre, de commencer en citant cette discussion.
Pour la saisie de l'utilisateur qui vient de stdin
, c'est à dire la saisie au clavier, fgets()
sera un meilleur choix. Il est beaucoup plus indulgent en ce que la chaîne qu'il lit peut être entièrement validée avant de conversion est tenté
L'une des rares fois à l'aide d'un formulaire de scanf(): fscanf() serait d'accord pour utiliser peut-être lors de la conversion d'entrée à partir d'un très contrôlé source, c'est à dire à partir de la lecture d'un strictement fichier au format de répéter prévisible des champs.
Pour une discussion plus approfondie, cette comparaison des deux faits saillants supplémentaires, les avantages et les inconvénients des deux.
Edit: pour répondre à l'OP, la question de savoir à propos de dépassement de capacité:
"Une chose que je veux poser est: même si nous utiliser fgets ce qu'il se passe si l'utilisateur de saisir des caractères plus que limite (je veux dire que beaucoup de
caractères), de débordement de la mémoire tampon? Ensuite, la façon de traiter avec
il?"
[fgets()](https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm il est joliment conçu pour empêcher le débordement de la mémoire tampon, en utilisant simplement ses paramètres correctement, par exemple:
char buffer[100] = {0};
...
while fgets(buffer, sizeof buffer, stdin);
Cela empêche d'entrée supérieure à la taille de la mémoire tampon en cours de traitement, donc de prévenir les débordements.
même en utilisant scanf()
la prévention de débordement de la mémoire tampon est assez simple: Utiliser un spécificateur de largeur dans la chaîne de format. Si vous voulez lire d'entrée, par exemple, et la limite de taille d'entrée de l'utilisateur à partir de 100 caractères max, le code devrait inclure les éléments suivants:
char buffer[101] = {0};// includes space for 100 + 1 for NULL termination
scanf("%100s", buffer);
^^^ width specifier
Cependant, avec les numéros, le débordement n'est pas si agréable à l'aide de scanf()
. Pour le démontrer, utilisez ce simple code, la saisie des deux valeurs indiquées dans le commentaire de l'un par série:
int main(void)
{
int val = 0;
// test with 2147483647 & 2147483648
scanf("%d", &val);
printf("%d\n", val);
return 0;
}
Pour la deuxième valeur, mon système lance le suivant:
NON-FATAL RUN-TIME ERROR: "test.c", line 11, col 5, thread id 22832: Function scanf: (errno == 34 [0x22]). Range error
`
Ici, vous avez besoin de lire une chaîne de caractères, puis suivez avec une chaîne à nombre de conversion à l'aide de l'un des strto_()
fonctions: strtol(), strtod(), ...). Les deux comprennent la capacité de test de débordement avant de provoquer un moment de l'exécution d'avertissement ou d'erreur. Notez que l'utilisation de atoi()
, atod()
ne protège pas de dépassement de soit.