En utilisant le code suivant:
char *name = malloc(sizeof(char) + 256);
printf("What is your name? ");
scanf("%s", name);
printf("Hello %s. Nice to meet you.\n", name);
Un utilisateur peut entrer son nom, mais lorsqu'il entre un nom avec un espace comme Lucas Aardvark
, scanf()
il coupe simplement tout après Lucas
. Comment scanf()
autoriser les espaces
sizeof(char) + 256
c'était une faute de frappe.Réponses:
Les gens (et en particulier les débutants) ne devraient jamais utiliser
scanf("%s")
ougets()
ou toute autre fonction qui n'a pas de protection contre le dépassement de la mémoire tampon, à moins que vous ne sachiez avec certitude que l'entrée sera toujours d'un format spécifique (et peut-être même pas dans ce cas).N'oubliez pas que
scanf
signifie «numérisation formatée» et il y a un peu moins formaté que les données saisies par l'utilisateur. C'est l'idéal si vous avez un contrôle total sur le format des données d'entrée mais généralement inadapté à la saisie utilisateur.Utilisez
fgets()
(qui a une protection contre le débordement de tampon) pour obtenir votre entrée dans une chaîne etsscanf()
pour l'évaluer. Puisque vous voulez juste ce que l'utilisateur a entré sans analyse, vous n'avez pas vraiment besoinsscanf()
dans ce cas de toute façon:la source
fgets()
. Il semble en fait plus facile à utiliser alorsscanf()
. +1scanf
comportement est indéfini si la conversion numérique déborde ( N1570 7.21.6.2p10 , dernière phrase, libellé inchangé depuis C89), ce qui signifie qu'aucune desscanf
fonctions ne peut être utilisée en toute sécurité pour la conversion numérique d'une entrée non approuvée.scanf
dans un devoir, ils ont eu tort de le faire, et vous pouvez leur dire que je l'ai dit, et s'ils veulent discuter avec moi à ce sujet , mon adresse e-mail se trouve facilement dans mon profil.Essayer
J'espère que cela pourra aider.
la source
s
à la fin de la chaîne d'entrée car il est à la fois superflu et incorrect dans certains cas (comme indiqué dans les commentaires précédents).[
est son propre spécificateur de format plutôt qu'une variation de celui-s
ci.Cet exemple utilise un scanset inversé, donc scanf continue à prendre des valeurs jusqu'à ce qu'il rencontre un '\ n' - nouvelle ligne, donc les espaces sont également enregistrés
la source
%20[^\n]s
pour éviter les débordements de mémoire tampons
là-bas!Vous pouvez utiliser ceci
Ou ca
DEMO
la source
scanf("%19[^\n]", name);
(toujours +1 pour la réponse concise)sizeof(char)
est par définition toujours 1, il n'est donc pas nécessaire de multiplier par elle.N'utilisez pas
scanf()
pour lire des chaînes sans spécifier une largeur de champ. Vous devez également vérifier les valeurs de retour pour les erreurs:Sinon, utilisez
fgets()
:la source
Vous pouvez utiliser la
fgets()
fonction pour lire une chaîne ou l'utiliserscanf("%[^\n]s",name);
pour que la lecture de la chaîne se termine lors de la rencontre d'un caractère de nouvelle ligne.la source
s
n'y appartient pasgetline()
Fait désormais partie de POSIX, néanmoins.
Il prend également en charge le problème d'allocation de tampon que vous avez posé précédemment, bien que vous deviez vous occuper de
free
la mémoire.la source
Si quelqu'un cherche toujours, voici ce qui a fonctionné pour moi: lire une longueur arbitraire de chaîne, y compris des espaces.
Merci à de nombreuses affiches sur le web pour partager cette solution simple et élégante. Si cela fonctionne, le mérite leur revient, mais toutes les erreurs sont les miennes.
la source
errno
et nettoyer la mémoire allouée.s
n'appartient pas là après le scansetVous pouvez utiliser
scanf
à cette fin avec une petite astuce. En fait, vous devez autoriser l'entrée de l'utilisateur jusqu'à ce que l'utilisateur clique sur Entrée (\n
). Cela prendra en compte tous les caractères, y compris l' espace . Voici un exemple:Comment ça marche? Lorsque l'utilisateur saisit des caractères à partir de l'entrée standard, ils seront stockés dans une variable chaîne jusqu'au premier espace vide. Après cela, le reste de l'entrée restera dans le flux d'entrée et attendra le prochain scanf. Ensuite, nous avons une
for
boucle qui prend char par char du flux d'entrée (till\n
) et les ajoute à la fin de la variable de chaîne , formant ainsi une chaîne complète identique à l'entrée utilisateur depuis le clavier.J'espère que cela aidera quelqu'un!
la source
Bien que vous ne devriez vraiment pas utiliser
scanf()
pour ce genre de chose, car il existe de bien meilleurs appels tels quegets()
ougetline()
, cela peut être fait:la source
gets
été déconseillé et supprimé ( stackoverflow.com/questions/30890696/why-gets-is-deprecated ) de la norme. Il est encore pire quescanf
parce qu'au moins ce dernier a des moyens de le rendre sûr.la source
s
n'appartient pas là après le scanset