Quelqu’un pourrait-il m’expliquer les différences entre strtok()
et strsep()
? Quels sont leurs avantages et inconvénients? Et pourquoi devrais-je choisir un sur l’autre.
Extrait du manuel de la bibliothèque GNU C – Recherche de jetons dans une chaîne :
Une différence entre
strsep
etstrtok_r
est que si la chaîne d’entrée contient plus d’un caractère du délimiteur d’une ligne,strsep
renvoie une chaîne vide pour chaque paire de caractères du délimiteur. Cela signifie qu’un programme devrait normalement testerstrsep
renvoyant une chaîne vide avant de la traiter.
Une différence majeure entre strtok()
et strsep()
est que strtok()
est normalisé (par le standard C, et donc aussi par POSIX), mais strsep()
n’est pas normalisé (par C ou POSIX; il est disponible dans GNU C Bibliothèque et a son origine sur BSD). Ainsi, le code portable est plus susceptible d’utiliser strtok()
que strsep()
.
Une autre différence est que les appels à la fonction strsep()
sur différentes chaînes peuvent être entrelacés, alors que vous ne pouvez pas le faire avec strtok()
(bien que vous puissiez le faire avec strtok_r()
). Ainsi, l’utilisation de strsep()
dans une bibliothèque ne rompt pas accidentellement le code, alors que l’utilisation de strtok()
dans une fonction de bibliothèque doit être documentée, car un autre code utilisant strtok()
ne peut pas appeler la fonction de bibliothèque.
La page de manuel de strsep()
sur kernel.org indique:
La fonction strsep () a été introduite pour remplacer strtok (3), cette dernière ne pouvant pas gérer les champs vides.
Ainsi, l’autre différence majeure est celle soulignée par George Gaál dans sa réponse; strtok()
autorise plusieurs délimiteurs entre un seul jeton, alors que strsep()
attend un seul délimiteur entre les jetons et interprète les délimiteurs adjacents comme un jeton vide.
strsep()
et strtok()
modifient leurs chaînes d’entrée et ne permettent pas d’identifier le caractère de délimitation marqué la fin du jeton (car les deux écrivent un NUL '\0'
sur le séparateur après la fin du jeton).
strsep()
lorsque vous voulez des jetons vides plutôt que de permettre plusieurs délimiteurs entre les jetons, et lorsque la portabilité ne vous dérange pas. strtok_r()
lorsque vous souhaitez autoriser plusieurs délimiteurs entre les jetons et que vous ne voulez pas de jetons vides (et que POSIX est suffisamment portable pour vous). strtok()
lorsque quelqu’un menacerait votre vie si vous ne le faites pas. Et vous ne l’utiliseriez que pendant assez longtemps pour vous sortir de la situation en danger de mort; vous en abandonneriez alors l’usage. C’est toxique; ne l’utilise pas. Il serait préférable d’écrire votre propre strtok_r()
ou strsep()
plutôt que d’utiliser strtok()
. strtok()
toxique? La fonction strtok()
est toxique si elle est utilisée dans une fonction de bibliothèque. Si votre fonction de bibliothèque utilise strtok()
, il doit être documenté clairement.
C’est parce que:
strtok()
et appelle votre fonction qui utilise également strtok()
, vous interrompez la fonction appelante. strtok()
, l’utilisation de strtok()
sera interrompue. strtok()
à un moment donné, au cours d’une séquence d’appels strtok()
. La racine de ce problème est l’état enregistré entre les appels qui permet à strtok()
de continuer là où il s’était arrêté. Il n’existe aucun moyen sensé de résoudre le problème autre que “n’utilisez pas strtok()
“.
strsep()
s’il est disponible. strtok_r()
de POSIX si elle est disponible. strtok_s()
s’il est disponible. strtok_s()
l’ISO / CEI 9899: 2011, Annexe K.3.7.3.1, mais son interface est différente de strtok_r()
et de strtok_s()
de Microsoft. strsep()
BSD strsep()
:
char *strsep(char **ssortingngp, const char *delim);
POSIX strtok_r()
:
char *strtok_r(char *ressortingct s, const char *ressortingct sep, char **ressortingct state);
Microsoft strtok_s()
:
char *strtok_s(char *strToken, const char *strDelimit, char **context);
Annexe K strtok_s()
:
char *strtok_s(char * ressortingct s1, rsize_t * ressortingct s1max, const char * ressortingct s2, char ** ressortingct ptr);
Notez que cela a 4 arguments, pas 3 comme dans les deux autres variantes sur strtok()
.