J'essaie d'utiliser cette fonction dans un programme C qui doit pouvoir compiler sous Linux et Windows. Au début, j’ai essayé d’utiliser strtok_r, mais lorsque j’ai compilé sous Windows, il s’est plaint de l’absence de la fonction et dit qu’il supposerait qu’il s’agit d’une fonction externe, mais a échoué. J'ai ensuite utilisé strtok_s et c'est compilé! Ensuite, j'ai essayé sur Linux, mais maintenant, on se plaint de l'existence d'une "référence non définie à 'strtok_s'".
Est-ce que l'une des fenêtres ne fonctionne que et l'autre une fonction Linux ??? Que puis-je faire pour le compiler sur les deux?
Ces deux fonctions sont des idiomes vraiment laids et non intuitifs pour l'analyse de chaînes, et ne répondent généralement pas aux exigences de votre application particulière de manière subtile. Même plus pour la simple strtok
en standard C. Jetez-les simplement et écrivez votre propre code pour le parcourir sur le tableau char
et le diviser au besoin. strchr
, strspn
et strcspn
peuvent être utiles, ou vous pouvez simplement travailler à partir de zéro sur le tableau.
strtok_s
est simplement la version Windows de strtok_r
qui est standard partout ailleurs.
Une façon (courante, je pense) de rendre un programme portable en ce qui concerne des fonctions telles que strtok_s
/strtok_r
est d’utiliser le pré-processeur:
#if defined(_WIN32) || defined(_WIN64)
/* We are on Windows */
# define strtok_r strtok_s
#endif
Les prototypes et les fonctionnalités étant identiques, vous ne pouvez désormais utiliser que strtok_r
.
Je n'ai pas assez de réputation pour commenter d'autres réponses, je vais donc devoir fournir les miennes.
Pour adresser cette déclaration:
"strtok_s est une version sûre de Strtok sous Windows en cas de débordement de tampon. Le strtok standard sous Windows est thread-safe ..."
Ce n'est pas vrai. strtok_s est la version thread-safe du compilateur MSVC. strtok n'est pas thread-safe!
Pour adresser cette déclaration:
"Cela casserait probablement si on compilait sur cygwin qui se présente comme une fenêtre mais dont les interfaces posix comme strtok_r sont déjà définies."
Encore une fois, pas vrai. La différence est quel compilateur vous utilisez. Lorsque vous utilisez le compilateur Visual C++ de Microsoft, MSVC, la fonction est strtok_s. Un autre compilateur, tel que la collection de compilateurs GNU, GCC, peut utiliser une implémentation de bibliothèque standard différente, telle que strtok_r. Pensez au compilateur, et non à la plate-forme cible, pour identifier la fonction à utiliser.
À mon avis, la réponse de Joachim Pileborg est la meilleure sur cette page. Cependant, il faut une petite modification:
#if defined(_WIN32) /* || defined(_WIN64) */
#define strtok_r strtok_s
#endif
_WIN32 et _WIN64 sont des macros prédéfinies fournies par le compilateur MSVC. _WIN64 est défini lors de la compilation d'une cible 64 bits. _WIN32 est défini pour les cibles 32 et 64 bits. Il s'agit d'un compromis fait par Microsoft pour assurer la compatibilité avec les versions antérieures. _WIN32 a été créé pour spécifier l'API Win32. A présent, vous devez considérer que _WIN32 spécifie une API Windows - elle n'est pas spécifique à une cible 32 bits.
Juste pour clarifier. strtok est thread-safe sous Windows. strtok utilise une variable TLS pour conserver le dernier pointeur de chaque thread. Cependant, vous ne pouvez pas utiliser strtok pour entrelacer l’accès à plus d’une chaîne de jetons par thread. strtok_r et strtok_s répondent tous deux à ce problème d'entrelacement en permettant à l'utilisateur de conserver le contexte via le troisième paramètre. J'espère que cela t'aides.
strtok_r est une version thread-safe de strtok sur les systèmes POSIX
strtok_s est une version sécurisée de la mémoire tampon de strtok sous Windows. Le strtok standard sur Windows est thread-safe, donc strtok_s devrait l'être.
MinGW prédéfinit également _WIN32
mais il supporte strtok_r
, donc je ne pense pas que ce soit une bonne idée de vérifier la macro _WIN32
. Il est préférable de vérifier la macro _MSC_VER
, qui est la macro pour Microsoft Visual Studio.
#ifdef _MSC_VER
#define strtok_r strtok_s
#endif
AVERTISSEMENT: Microsoft strtok_s
et C11 strtok_s
sont complètement différents! Microsoft strtok_s
n'a que 3 paramètres, alors que C11 strtok_s
en a 4, il peut donc s'agir d'un problème compatible à l'avenir.
Le prototype de Microsoft strtok_s
est
char* strtok_s(char* str, const char* delimiters, char** context);
Le prototype de C11 strtok_s
est
char *strtok_s(char *restrict str, rsize_t *restrict strmax, const char *restrict delim, char **restrict ptr);