scanf(“%[^\n]s”,a) vs obtient(a)
On m'a dit que scanf ne doit pas être utilisé lorsque l'utilisateur entre une chaîne de caractères. Au lieu de cela, optez pour gets() par la plupart des experts et les utilisateurs sur StackOverflow. Je n'ai jamais demandé sur StackOverflow pourquoi on ne devrait pas utiliser scanf plus obtient pour les chaînes de caractères. Ce n'est pas la question mais la réponse à cette question est grandement apprécié.
Arrive maintenant à la question. Je suis tombé sur ce type de code -
scanf("%[^\n]s",a);
Ce lit une chaîne de caractères jusqu'à ce que les entrées de l'utilisateur un caractère de nouvelle ligne, en considérant les espaces en blanc également comme une chaîne de caractères.
Est-il un problème si j'utilise
scanf("%[^\n]s",a);
au lieu de?
Est devient de plus en plus optimisé que la fonction scanf comme il semble, est purement dédiés à la gestion des chaînes de caractères. S'il vous plaît laissez-moi savoir à ce sujet.
Mise à jour
Cette lien m'a aidé à mieux le comprendre.
gets
n'est pas une très bonne idée, soit à cause du risque de dépassements de la mémoire tampon. Utilisation fgets
.Merci, mais à ma connaissance fgets est pour la manipulation de fichiers de droite? Je viens d'apprendre le f indique le mode fichier, alors pourquoi est-ce qu'ils utilisé obtient et fgets()
Vous pouvez lire l'entrée standard avec
fgets
en passant stdin
comme le dernier paramètre. L'avantage de l'utilisation de fgets
sur gets
est qu'avec fgets
, vous pouvez spécifier la longueur de votre tampon, la prévention fgets
à partir de la lecture de beaucoup de données. gets
est un risque pour la sécurité, et ils n'ont jamais fixe pour des raisons de compatibilité descendante.Tout
f*
fonction (par exemple, fscanf
) peut être utilisé sur le stdin
descripteur de fichier pour émuler le non-f*
version (dans ce cas, fscanf(stdin, ...)
est exactement équivalente à scanf(...)
).Non, la lecture de
stdin
toujours attendre un retour à la ligne. Toutefois, si l'utilisateur entre des personnages de plus fgets
demandé, elles sont stockées dans un tampon dans le cadre de la FILE *
de la structure, et de ne pas être accessible que par vous. Un deuxième appel à fgets
volonté, au lieu de lire plus de commentaires des utilisateurs, de retour de plus de données à partir de la mémoire tampon, jusqu'à ce qu'elle est vide. (fgetc
les autres caractères d'un-à-un-temps les fonctions de faire exactement la même chose.)
OriginalL'auteur niko | 2011-11-18
Vous devez vous connecter pour publier un commentaire.
gets(3)
est dangereux et devrait être évitée à tous les frais. Je ne peux pas envisager une utilisation oùgets(3)
est pas une faille de sécurité.scanf(3)
's%s
est aussi dangereux, vous devez utiliser le champ "largeur" du rédacteur de devis pour indiquer la taille de la mémoire tampon allouée. Sans la largeur du champ, cette routine est aussi dangereux quegets(3)
:La bibliothèque C de GNU fournit la
a
modificateur à%s
qui alloue de la mémoire tampon pour vous. Cette non-portable extension est probablement moins difficile à utiliser correctement:%[
ou%s
.%64[a-z]
lit jusqu'à 64 caractères alphabétiques en minuscules, et%64s
lit jusqu'à 64 non-caractères espace.Ça m'apprendra à écrire sur un vide (et donc distrait 🙂 estomac -- j'ai lu les deux
scanf(3)
etscanf(3posix)
la recherche de signe que j'avais tort.... mais ça y est: La chaîne d'entrée s'arrête à l'espace blanc ou au maximum de la largeur de champ, selon la première éventualité. merci Beaucoup!char name[64]; scanf("%64s", name);
ne devrait-elle pas êtrescanf("%63s", name);
? ce qui laisse un emplacement pourNUL
caractère.wow. Je ne peux pas croire que j'ai fait cette erreur. Excellente prise!
Mais quelle est cette réponse pertinente à la question? La question est à propos de la mise en œuvre de ligne d'entrée (et de ne pas sauter les espaces). Ni
%s
nia
modificateur sont même près du sujet.OriginalL'auteur sarnold
Tout d'abord, il n'est pas clair ce que
s
est en train de faire dans votre chaîne de format. Le%[^\n]
partie est auto-suffisante spécificateur de format. Il n'est pas un modificateur pour%s
format, comme vous semblez le croire. Cela signifie que"%[^\n]s"
chaîne de format sera interprété parscanf
que deux indépendants des spécificateurs de format:%[^\n]
suivi par un seuls
. Ce sera directscanf
de tout lire jusqu'\n
est rencontré (en laissant\n
non lus), puis d'exiger que le prochain caractère ests
. Cela n'a tout simplement pas de sens. Pas d'entrée correspondra à une telle auto-contradictoire format.Deuxièmement, ce qui était apparemment le signifié est
scanf("%[^\n]", a)
. C'est assez proche de [plus disponible]gets
(oufgets
), mais ce n'est pas la même.scanf
exige que chaque spécificateurs de format correspond à au moins une entrée de caractères.scanf
échouera et l'annuler si elle ne correspond à aucune entrée de caractères pour le spécificateur de format. Cela signifie quescanf("%[^\n]",a)
n'est pas capable de lire le vide, les lignes d'entrée, c'est à dire les lignes qui contiennent\n
caractère immédiatement. Si vous nourrissez une ligne de ce type dans le ci-dessusscanf
, il sera de retour0
pour indiquer l'échec et de laissera
inchangé. C'est très différent de la façon typique de la ligne de saisie sur les fonctions de travail.(Ce qui est plutôt surprenant et apparemment illogique correctement de
%[]
format. Personnellement, je préfère%[]
pour être en mesure de faire correspondre les séquences vides et de produire des chaînes vides, mais ce n'est pas comment la normescanf
).Si vous voulez lire l'entrée en ligne par voie de mode,
fgets
est votre meilleure option.scanf("%[^\n]",a)
,'\n'
reste dansstdin
.)OriginalL'auteur AnT