strtok_s - ¿Cómo funciona la función strtok en C?
strtok php (4)
Esta pregunta ya tiene una respuesta aquí:
- ¿Cómo strtok () divide la cadena en tokens en C? 13 respuestas
Encontré este programa de ejemplo que explica la función strtok
:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string /"%s/" into tokens:/n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s/n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
Sin embargo, no veo cómo esto es posible trabajar.
¿Cómo es posible que pch = strtok (NULL, " ,.-");
devuelve un token nuevo. Quiero decir, estamos llamando a strtok
con NULL
. Esto no tiene mucho sentido para mí.
Dos cosas que strtok
saber sobre strtok
. Como se mencionó, "mantiene el estado interno". Además, desordena la cadena que lo alimenta . Esencialmente, escribirá un ''/0''
donde encuentre el token que proporcionó y devuelve un puntero al comienzo de la cadena. Internamente mantiene la ubicación del último token; y la próxima vez que lo llames, comienza desde allí.
El corolario importante es que no se puede usar strtok
en const char* "hello world";
tipo de cadena, ya que obtendrá una infracción de acceso cuando modifique el contenido de una cadena const char*
.
Lo "bueno" de strtok
es que en realidad no copia cadenas, por lo que no necesita administrar la asignación de memoria adicional, etc. Pero a menos que entienda lo anterior, tendrá problemas para usarlo correctamente.
Ejemplo: si tiene "this, is, a, string", las llamadas sucesivas a strtok
generarán punteros de la siguiente manera ( ^
es el valor devuelto). Tenga en cuenta que el ''/0''
se agrega donde se encuentran los tokens; esto significa que la cadena de origen se modifica:
t h i s , i s , a , s t r i n g /0 this,is,a,string
t h i s /0 i s , a , s t r i n g /0 this
^
t h i s /0 i s /0 a , s t r i n g /0 is
^
t h i s /0 i s /0 a /0 s t r i n g /0 a
^
t h i s /0 i s /0 a /0 s t r i n g /0 string
^
Espero que tenga sentido.
La strtok()
almacena datos entre llamadas. Utiliza esos datos cuando lo llamas con un puntero NULO.
Desde http://www.cplusplus.com/reference/cstring/strtok/ :
El punto donde se encontró el último token se mantiene internamente por la función que se usará en la próxima llamada (no se requieren implementaciones particulares de la biblioteca para evitar las carreras de datos).
La función strtok
almacena datos en una variable estática interna que se comparte entre todos los subprocesos.
Para la seguridad de los hilos debes usar strtok_r
De http://www.opensource.apple.com/source/Libc/Libc-167/string.subproj/strtok.c
Echa un vistazo a static char *last;
char *
strtok(s, delim)
register char *s;
register const char *delim;
{
register char *spanp;
register int c, sc;
char *tok;
static char *last;
if (s == NULL && (s = last) == NULL)
return (NULL);
/*
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
*/
cont:
c = *s++;
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
if (c == sc)
goto cont;
}
if (c == 0) { /* no non-delimiter characters */
last = NULL;
return (NULL);
}
tok = s - 1;
/*
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
* Note that delim must have one NUL; we stop if we see that, too.
*/
for (;;) {
c = *s++;
spanp = (char *)delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
last = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}
strtok
mantiene el estado interno. Cuando lo llama con un valor distinto de NULL, se reinicializa para usar la cadena que proporciona. Cuando lo llamas con NULL
, usa esa cadena y cualquier otro estado que tenga actualmente para devolver el siguiente token.
Debido a la forma en que funciona strtok
, debe asegurarse de vincularse con una versión de multiproceso del tiempo de ejecución de C si está escribiendo una aplicación de multiproceso. Esto asegurará que cada subproceso obtenga su propio estado interno para strtok
.