Max longueur de la chaîne à l'aide de scanf -> C ANSI
J'ai:
#define MAX_STR_LEN 100
et je veux mettre en scanf
modèle pour que je puisse contrôler la longueur de la chaîne:
scanf("%100[^\n]s",sometext)
J'ai essayé:
scanf("%MAX_STR_LEN[^\n]s",sometext)
scanf("%"MAX_STR_LEN"[^\n]s",sometext)
scanf("%",MAX_STR_LEN,"[^\n]s",sometext)
Et ça ne fonctionne pas. Je veux juste éviter le débordement de la mémoire tampon depuis "sometext" est attribuée avec malloc(MAX_STR_LEN)
...
Des idées?
- Discuté ici.
- Comment pouvez-vous utiliser
MAX_STR_LEN
au sein d'une chaîne de format? - puisque c'est la stricte norme ANSI C, je n'ai pas vraiment accès à la vraie variable de chaîne. J'ai besoin de le faire: char *somestring et puis malloc...
- Est probablement trop tard , mais j'ai fait cette fonction uniquement pour résoudre ce problème. github.com/tsw1985/Gscanf
- Outre les réponses ici, je tiens à souligner que si vous utilisez
"%100s"
l'allocation doit être 101 octets, donc dans votre exemple, vous avez besoinmalloc(MAX_STR_LEN+1)
, ou"%99s"
.
Vous devez vous connecter pour publier un commentaire.
Je n'étais pas heureux avec l'une de ces solutions, donc j'ai plus amples recherches et découvert GNU GCC macro stringification
qui peut être utilisé comme:
Peut-être VS2010 propose quelque chose de similaire?
Puis ne pas utiliser
scanf()
. À tous.Si vous numérisez des lignes de texte, de ne pas
#define MAX_STR
soit. Vous pouvez hazLINE_MAX
dans<limits.h>
(si vous ciblez POSIX systèmes compatibles):devrait faire l'affaire.
Comme presque tout le monde le dit, il est préférable d'utiliser
fgets(..., stdin)
pour gérer ce problème.Dans le lien suivant, j'ai proposé un coffre-fort et une technique correcte qui vous permettent de remplacer
scanf()
par une méthode plus sûre, par le biais d'un solide macro:Une macro en toute sécurité remplace scanf()
La macro que j'ai proposé (travail compatible avec C99 compilateurs) est
safe_scanf()
, comme le montre le programme suivant:Vous auriez à tune la valeur de
MAXBUFF
en fonction de vos besoins...Bien que la macro
safe_scanf()
est assez solide,il y a une certaine faiblesse dans l'utilisation de la macro approche:
Manque la vérification de type pour les paramètres, manque de "retour" des valeurs (qui se distingue peu de la "vraie"
scanf()
fonction, qui renvoie un int, avec de précieuses informations pour la vérification des erreurs), et ainsi de suite.Tous les problèmes ont une solution, mais il fait partie d'un autre sujet...
Peut-être, plus exactement la solution consiste à définir une fonction
my_scanf()
avec un nombre variable de paramètres, en invoquant lastdarg.h
bibliothèque, joint à une combinaison defgets()
etvsscanf()
. Ici vous avez le code:La fonction my_scanf() est le prototype
Il accepte une chaîne de format
fmt
qui se comporte de la même manière que toute autrescanf()
-comme le fait.Le 2ème paramètre est le nombre maximum de caractères qui seront effectivement acceptées à partir de l'entrée standard (clavier).
La valeur de retour est une int, qui est
EOF
simaxbuff
n'a pas de sens, ou bien une entrée d'erreur qui s'est passé. Si une valeur non-négative est retourné, c'est le même qui serait retourné par les fonctions standardsscanf()
ouvsscanf()
.L'intérieur de la fonction,
maxbuff
est incrémenté de 1, parce quefgets()
fait de la place pour un '\0' caractère.Non-valeurs positives de
maxbuff
sont immédiatement rejetées.fgets()
va lire une chaîne de caractères est lu à partir destdin
(clavier) avec de la place pour au plusmaxbuff
caractères, y compris les '\n'.Si l'utilisateur a entré une chaîne très longue, alors il sera bu tronquée, et une sorte de "chasse d'eau" mécanisme est nécessaire afin d'éliminer tous les caractères à la prochaine '\n' (ENTRER). Si pas, la prochaine clavier de la lecture, pourraient avoir des personnages plus âgés, ce n'est pas souhaitée à tous.
La condition de "rinçage" est que
fgets()
n'a pas atteint '\n' après la lecture destdin
.C'est le cas si, et seulement si,
buffer[maxbuff - 1]
n'est pas égal à '\0' ni de '\n'.(Vérifier!)
Enfin, une combinaison appropriée de
stdarg.h
macros et la fonctionvsscanf()
est utilisé pour traiter la liste variable de paramètres.Recommander la
fgets(buffer, sizeof(buffer), stdin)
approche.Si vous encore souhaitez utiliser scanf (), vous pouvez créer son format au moment de l'exécution.
ou re-définir MAX_STR_LEN être une chaîne
Recommandent encore l'
fgets()
.Note
fgets()
va mettre les espaces de début et de fin du\n
dans votre tampon alors que" %[^\n]"
ne sera pas.BTW: la fuite
s
dans votre formats n'est pas susceptible de faire ce que vous pensez.Comment sur
*
utilisation dansscanf()
. Je suis certaine que vous souhaitez modifier votre post. Dans printf() utilisation,*
lit un entier de taille, mais pas dansscanf()
.*
signifie "Une option de départ astérisque indique que les données sont à lire dans le flux, mais ignoré". Une tout autre fonction.