Si le code est
scanf("%s\n",message)
contre
gets(message)
quelle est la différence? Il semble que les deux reçoivent un message.
La différence fondamentale [en référence à votre scénario particulier],
scanf()
finit de prendre des informations lorsqu'il rencontre un whitespace
, newline
ou EOF
gets()
considère un espace comme faisant partie de la chaîne d'entrée et termine l'entrée lorsque newline
ou EOF
est rencontré.
Cependant, pour éviter les erreurs de buffer overflow et pour éviter les risques de sécurité, il est plus sûr d’utiliser fgets()
.
Désambiguïsation: dans le contexte suivant, je considérerais "safe" s'il ne posait pas problème, s'il était utilisé correctement. Et "unsafe" si "unsafetyness" ne peut pas être manipulé.
scanf("%s\n",message)
contre
gets(message)
Quelle est la différence?
En termes de sécurité, il n'y a pas de différence. Les deux sont lus depuis Standard Input
et peuvent très bien déborder message
, si l'utilisateur entre plus de données, puis message
fournit de la mémoire.
Attendu que scanf()
vous permet d’être utilisé en toute sécurité en spécifiant la quantité maximale de données à analyser dans:
char message[42];
...
scanf("%41s", message); /* Only read in one few then the buffer (messega here)
provides as one byte is necessary to store the
C-"string"'s 0-terminator. */
Avec gets()
il est non possible de spécifier le nombre maximal de caractères à lire, c’est pourquoi ce dernier ne doit pas être utilisé !
La principale différence est que gets
lit jusqu'à ce que EOF ou \n
, tandis que scanf("%s")
se lit jusqu'à ce qu'aucun espace n'ait été rencontré. scanf
fournit également plus d'options de formatage, mais en même temps, la sécurité de type est pire que gets
.
Une autre grande différence est que scanf
est une fonction C standard, alors que gets
a été supprimé de la langue, car elle était à la fois superflue et dangereuse: il n'y avait pas de protection contre les dépassements de mémoire tampon. Cependant, le même défaut de sécurité existe avec scanf, de sorte queaucune de ces deux fonctions ne devrait être utilisée dans le code de production.
Vous devriez toujours utiliser fgets
, le standard C lui-même le recommande même, voir C11 K.3.5.4.1
Pratique recommandée
6 La fonction fgets permet d’écrire correctement programmes pour traiter en toute sécurité les lignes d’entrée trop longues à stocker dans le résultat tableau. En général, cela nécessite que les appelants de gadgets fassent attention à la présence ou l'absence d'un caractère de nouvelle ligne dans le tableau de résultats . Pensez à utiliser fgets (avec tout traitement nécessaire basé sur les caractères New-line) au lieu de gets_s.
(c'est moi qui souligne)
gets
- Lit les caractères de stdin et les stocke sous forme de chaîne.
scanf
- Lit les données de stdin et les stocke selon le format spécifié dans l'instruction scanf
comme %d
, %f
, %s
, etc.
Il y a plusieurs. La première est que gets () obtiendra uniquement les données de chaîne de caractères. Une autre est que gets () n’obtient qu’une variable à la fois. scanf () est en revanche un outil beaucoup plus souple. Il peut lire plusieurs éléments de différents types de données.
Dans l'exemple que vous avez choisi, il n'y a pas beaucoup de différence.
obtient: ->
gets() reads a line from stdin into the buffer pointed to by s until
either a terminating newline or EOF, which it replaces with a null byte ('\0').
BOGUES: ->
Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead.
scanf: ->
The scanf() function reads input from the standard input stream stdin;
PUNAISE
Some times scanf makes boundary problems when deals with array and
string concepts.
Dans le cas de scanf
, vous avez besoin du format mentionné, contrairement à in. Ainsi, dans gets
, vous entrez des caractères, des chaînes, des nombres et des espaces.
Dans le cas de scanf
, votre saisie prend fin dès qu’un espace blanc est rencontré.
Mais dans votre exemple, vous utilisez '% s' donc, ni gets()
ni scanf()
que les chaînes ne sont des pointeurs valides vers des tableaux d'une longueur suffisante pour contenir les caractères que vous leur envoyez. D'où peut facilement provoquer un débordement de tampon.
Astuce: utilisez fgets()
, mais cela dépend du cas d'utilisation
gets () est dangereux, par exemple: char str [1]; gets (str) si vous entrez plus que la longueur, il finira par SIGSEGV . si seulement peut utiliser gets, utilisez malloc comme variable de base.
Le concept selon lequel scanf ne prend pas d'espace est totalement faux. Si vous utilisez cette partie du code, il faudra également un espace blanc:
#include<stdio.h>
int main()
{
char name[25];
printf("Enter your name :\n");
scanf("%[^\n]s",name);
printf("%s",name);
return 0;
}
Là où l'utilisation de la nouvelle ligne ne cessera que de prendre des entrées. Cela signifie que si vous appuyez sur entrée seulement, alors il cessera de prendre des entrées.
Donc, il n'y a pratiquement pas de différence entre scanf et obtient des fonctions. C'est juste un moyen délicat de mise en œuvre.
scanf()
est un outil beaucoup plus flexible alors que gets()
n'obtient qu'une variable à la fois.