Quelles sont les différences entre strtok et strsep en C
Quelqu'un pourrait-il m'expliquer quelles sont les différences entre strtok()
et strsep()
?
Quels sont les avantages et les inconvénients?
Et pourquoi j'en choisirais un plutôt que l'autre.
2 réponses
à Partir de La Bibliothèque C de GNU manuel - trouver des jetons dans une chaîne:
Une différence entre
strsep
etstrtok_r
c'est que si la chaîne d'entrée contient plus d'un caractère de séparateur dans une rangéestrsep
renvoie une chaîne vide pour chaque paire de caractères de delimiter. Cela signifie qu'un programme normalement doit testerstrsep
retour une chaîne vide avant de la traiter.
Une différence majeure entre strtok()
et strsep()
que strtok()
est normalisée (par la norme, et donc aussi par POSIX) mais strsep()
n'est pas standardisé (par C ou POSIX; il est disponible dans la bibliothèque GNU C, et provient de BSD). Ainsi, le code portable est plus susceptible d'utiliser strtok()
strsep()
.
une autre différence est que les appels à strsep()
fonction sur différentes chaînes peuvent être intercalées, alors que vous ne pouvez pas faire cela avec strtok()
(si vous pouvez le faire avec strtok_r()
). Donc, à l'aide de strsep()
dans une bibliothèque ne casse pas accidentellement un autre code, alors qu'utiliser strtok()
dans une fonction de bibliothèque doit être documenté parce que l'autre code en utilisant strtok()
en même temps ne peut pas appeler la fonction de bibliothèque.
la page de manuel pour strsep()
kernel.org dit:
la fonction strsep() a été introduite en remplacement de strtok(3), puisque cette dernière ne peut pas gérer des champs vides.
ainsi, l'autre différence majeure est celle mise en évidence par George Gaál dans sa réponse; strtok()
permet des délimiteurs multiples entre un même token, alors que strsep()
attend un seul délimiteur entre les tokens, et interprète les délimiteurs adjacents comme un jeton vide.
strsep()
et strtok()
modifier leurs chaînes d'entrée et ne permet pas non plus d'identifier quel caractère de délimiteur a marqué la fin du token (parce que les deux écrivent un NUL!--21--> le séparateur après la fin du jeton).
Quand les utiliser?
- Vous utilisez
strsep()
quand vous voulez des tokens vides plutôt que d'autoriser des délimiteurs multiples entre les tokens, et quand vous ne vous souciez pas de la portabilité. - Vous utilisez
strtok_r()
quand vous voulez autoriser plusieurs délimiteurs entre les tokens et que vous ne voulez pas de tokens vides (et POSIX est suffisamment portable pour vous). - Vous utilisez uniquement
strtok()
quand quelqu'un menace votre vie si vous ne le faites pas. Et que vous souhaitez l'utiliser assez longtemps pour vous sortir de la vie en danger; il vous faudra alors renoncer à tout usage une fois de plus. Il est toxique; ne l'utilisez pas. Il serait mieux d'écrire votre proprestrtok_r()
oustrsep()
utilisationstrtok()
.
Pourquoi strtok()
toxique?
strtok()
la fonction est toxique si elle est utilisée dans une fonction de la bibliothèque. Si votre fonction de bibliothèque utilise strtok()
, il doit être clairement expliquées.
c'est parce Que:
- si une fonction d'appel utilise
strtok()
et appelle la fonction qui utilise aussistrtok()
, vous brisez la fonction d'appel. - Si votre fonction appelle une fonction qui s'appelle
strtok()
, ce qui va casser l'utilisation destrtok()
. - si votre programme est multithread, au plus un thread peut utiliser
strtok()
à tout moment-sur une séquence destrtok()
appeler.
La racine de ce problème est l'état sauvegardé entre les appels qui permet strtok()
pour continuer là où elle s'est arrêtée. Il n'y a pas d'autre moyen raisonnable de résoudre le problème que "ne pas utiliser strtok()
".
- Vous pouvez utiliser
strsep()
si elle est disponible. - vous pouvez utiliser POSIX's
strtok_r()
si elle est disponible. - vous pouvez utiliser
strtok_s()
si elle est disponible. - Nominalement, vous pouvez utiliser L'annexe K. 3 de la norme ISO/IEC 9899:2011.7.3.1 fonction
strtok_s()
, mais son interface est différente des deuxstrtok_r()
et Microsoftstrtok_s()
.
BSD strsep()
:
char *strsep(char **stringp, const char *delim);
POSIX strtok_r()
:
char *strtok_r(char *restrict s, const char *restrict sep, char **restrict state);
Microsoft strtok_s()
:
char *strtok_s(char *strToken, const char *strDelimit, char **context);
Annexe K strtok_s()
:
char *strtok_s(char * restrict s1, rsize_t * restrict s1max,
const char * restrict s2, char ** restrict ptr);
notez qu'il y a 4 arguments, pas 3 comme dans les deux autres variantes sur strtok()
.