funciones strtok. Descripción de funciones del lenguaje C. Descripción de algunas funciones para trabajar con cadenas.

4 respuestas

Dos cosas que debes saber sobre strtok. Como se mencionó, "mantiene el estado interno". Además, él arruinaste la línea que le das de comer. Básicamente, escribirá "\0" donde encontrará el token que proporcionó y devolverá un puntero al inicio de la línea. Internamente mantiene la ubicación del último token; y la próxima vez que lo llames, comenzará desde allí.

Una consecuencia importante es que no puedes usar strtok en una cadena como const char* "hello world"; ya que obtendrá una infracción de acceso al cambiar el contenido de una cadena const char*.

Lo "bueno" de strtok es que en realidad no copia cadenas, por lo que no es necesario administrar la asignación de memoria adicional, etc. Pero si no comprende lo anterior, tendrá problemas para usarlo.

Ejemplo. Si tiene "esto, es, una cadena", las llamadas sucesivas a strtok generarán punteros como este (el valor de ^ es el valor de retorno). Tenga en cuenta que se agrega "\0" donde se encuentran los tokens; esto significa que la línea original ha sido modificada:

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 cadena ^

Espero que esto tenga sentido.

La función strtok() almacena datos entre llamadas. Utiliza estos datos cuando los llamas con un puntero NULL.

El punto en el que se encontró el último token se almacena internamente mediante una función que se utilizará en la siguiente llamada (no se requiere una implementación de biblioteca específica para evitar fallas de datos).

strtok mantiene el estado interno. Cuando lo llama con un valor no NULL, se reinicia para usar la cadena que usted 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 a la versión multiproceso del tiempo de ejecución de C si está escribiendo una aplicación multiproceso. Esto asegura que cada hilo obtenga su propio estado interno para strtok.

La función strtok almacena datos en una variable estática interna que se comparte entre todos los subprocesos.

Para seguridad de subprocesos, debe usar strtok_r

Eche un vistazo al carácter estático *last;

Char * strtok(s, delim) registrar char *s; registrar const char *delim; ( registrar char *spanp; registrar int c, sc; char *tok; static char *last; if (s == NULL && (s = last) == NULL) return (NULL); /* * Saltar (span) al principio delimitadores (s += strspn(s, delim), algo así). == sc) goto cont ) if (c == 0) ( /* sin caracteres no delimitadores */ last = NULL; return (NULL); ) tok = s - 1; /* * Escanear token (buscar delimitadores: s += strcspn(s, delim), más o menos). * Tenga en cuenta que delim también debe tener un NUL; )delim; hacer ( if ((sc = *spanp++) == c) ( if (c == 0) s = NULL; else s[-1] = 0; last = s; return (tok); ) ) while (sc != 0); ) /* NO ALCANZADO */ )

compartir

1) Encuentra el siguiente token en la cadena de bytes terminada en nulo a la que apunta str. Los caracteres delimitadores se identifican mediante la cadena de bytes nulos a la que apunta delim.

Esta función se llama multiplicación múltiple para obtener tokens sucesivos de la misma cadena.

  • Si str! = cadena NULA! = NULL, la llamada se trata como la primera llamada a strtok para esa fila en particular. La función busca el primer carácter que No contenido en delim.
  • Si no se encontró dicho símbolo, entonces no contiene tokens y la función devuelve un puntero nulo.
  • Si se encuentra tal símbolo, será inicio del token. Luego, la función busca desde ese punto el primer carácter contenido en delim .
    • Si no se encuentra dicho carácter, str tiene solo un token y las llamadas futuras a strtok devuelven un puntero nulo.
    • Si se encuentra tal símbolo, reemplazado el carácter nulo "\0" y el puntero al siguiente carácter se almacenan en una ubicación estática para llamadas posteriores.
  • Luego, la función devuelve un puntero al comienzo del token.
  • Si str == NULL , la llamada se trata como llamadas posteriores a strtok: la función continúa desde donde lo dejó en la llamada anterior. El comportamiento es el mismo que si el puntero almacenado previamente se pasara como str.

El comportamiento no está definido a menos que str o delim sea un puntero a una cadena de bytes terminada en nulo.

2) Igual que (1) excepto que cada paso escribe el número de caracteres que quedan por ver en str en *strmax y escribe el estado interno del tokenizador en *ptr . Las llamadas repetidas (con un strmax nulo) deben pasar strmax y ptr con los valores almacenados por la llamada anterior. Además, se encuentran los siguientes errores en tiempo de ejecución y se llama a la función de controlador de restricciones actualmente instalada sin almacenar nada en el objeto señalado por ptr

  • strmax, delim o ptr - puntero nulo
  • en caso de llamada no inicial (con cadena nula), *ptr - puntero nulo
  • en la primera llamada *strmax es cero o mayor que RSIZE_MAX
  • la búsqueda del final del token llega al final de la cadena original (medida por el valor inicial *strmax)) sin encontrar un terminador nulo

El comportamiento no está definido si str apunta a una matriz de caracteres que no tiene un carácter nulo y strmax apunta a un valor que es mayor que el tamaño de esa matriz de caracteres. Como todas las funciones relacionadas con límites, solo se garantiza que strtok_s estará disponible si __STDC_LIB_EXT1__ está definido por la implementación y si el usuario define __STDC_WANT_LIB_EXT1__ para la constante entera 1 antes de incluir string.h .

opciones

Valor de retorno

Devuelve un puntero al comienzo del siguiente token o NULL si no hay más tokens.

La nota

Esta función es destructiva: escribe caracteres "\0" en los elementos de la cadena str. En particular, un literal de cadena no se puede utilizar como primer argumento de strtok.

Cada llamada a strtok modifica una variable estática: no es segura para subprocesos.

A diferencia de la mayoría de los otros tokenizadores, los delimitadores de strtok pueden ser diferentes para cada token posterior e incluso pueden depender del contenido de los tokens anteriores.

La función strtok_s se diferencia de la función strtok_r POSIX en que se almacena fuera de la cadena tokenizada y verifica las restricciones de tiempo de ejecución.

ejemplo

#definir __STDC_WANT_LIB_EXT1__ 1 #incluir #incluir int main(void) ( char input = "Un pájaro bajó por el camino"; printf("Analizando la cadena de entrada "%s"\n", input); char *token = strtok(input, " "); while( token) ( puts(token); token = strtok(NULL, " "); ) printf("Contenido de la cadena de entrada ahora: ""); for(size_t n = 0; n< sizeof input; ++n) input[n] ? printf("%c", input[n]) : printf("\\0"); puts("""); #ifdef __STDC_LIB_EXT1__ char str = "A bird came down the walk"; rsize_t strmax = sizeof str; const char *delim = " "; char *next_token; printf("Parsing the input string "%s"\n", str); token = strtok_s(str, &strmax, delim, &next_token); while(token) { puts(token); token = strtok_s(NULL, &strmax, delim, &next_token); } printf("Contents of the input string now: ""); for(size_t n = 0; n < sizeof str; ++n) str[n] ? printf("%c", str[n]) : printf("\\0"); puts("""); #endif }

Posible salida:

Analizando la cadena de entrada "Un pájaro bajó por el camino" Un pájaro bajó por el camino Contenido de la cadena de entrada ahora: "A\0bird\0came\0down\0the\0walk\0" Analizando la cadena de entrada "Un pájaro bajó por el walk" Un pájaro bajó por el camino Contenido de la cadena de entrada ahora: "A\0bird\0came\0down\0the\0walk\0"

  • C11 (ISO/CEI 9899:2011):
    • 7.24.5.8 Función strtok (p: 369-370)
    • K.3.7.3.1 Función strtok_s (p: 620-621)
  • C99 (ISO/CEI 9899:1999):
    • 7.21.5.8 Función strtok (p: 332-333)
  • C89/C90 (ISO/CEI 9899:1990):
    • 4.11.5.8 Función strtok
encuentra la primera ubicación de cualquier carácter en una línea, en otra línea
(función)

sólo los caracteres que no se encuentran en otra cadena de bytes
(función)
devuelve la longitud del segmento inicial máximo, que consta de
sólo los caracteres encontrados en otra cadena de bytes
(función)

(C95) (C11)

encuentra el siguiente token en una cadena ancha
(función)
Documentación C++ para strtok

Otros alias

strtok

REVISAR

#incluir

char *trazo(char *cadena, carácter constante *delim);
char *strtok_r(char *cadena, carácter constante *delim,carbonizarse**guardarptr);

Requisitos para la macro de prueba de propiedades para glibc (consulte característica_prueba_macros(7)):

strtok_r(): _SVID_SOURCE || _BSD_SOURCE || _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_FUENTE

DESCRIPCIÓN

Función strtok() divide una cadena en una secuencia de cero o más tokens no vacíos. En primera llamada strtok() la cadena a analizar debe especificarse en el argumento cadena. En cada llamada posterior que analiza la misma cadena, el valor cadena debe ser NULO.

En discusión delim Se especifica un conjunto de bytes que se consideran separadores de tokens en la cadena analizada. La persona que llama puede especificar diferentes líneas en delim en llamadas posteriores al analizar la misma cadena.

cada llamada strtok() devuelve un puntero a una cadena terminada en nulo que contiene el siguiente token. Esta línea no incluye un byte delimitador. Si no hay más fichas, entonces strtok() devuelve NULO.

Secuencia de llamada strtok(), que operan en una sola cadena, mantienen un puntero que especifica el punto en el que comienza la búsqueda del siguiente token. Primera llamada strtok() asigna a este puntero una referencia al primer byte de la cadena. El inicio del siguiente token se determina buscando hacia adelante en cadena el siguiente byte no es un delimitador. Si se encuentra un byte, se toma como el comienzo del siguiente token. Si no se encuentra dicho byte, entonces no hay más tokens y strtok() devuelve NULL (para una cadena vacía o delimitada, en cuyo caso se devolverá NULL la primera vez que se llame strtok()).

El final de cada token se encuentra mediante una búsqueda directa hasta que se encuentra un byte delimitador o un byte nulo final ("\0"). Si se encuentra un byte delimitador, se reemplaza con un byte nulo para terminar el token actual, y strtok() almacena un puntero al siguiente byte; este puntero se utilizará como punto de partida al buscar el siguiente token. En este caso strtok() devuelve un puntero al comienzo del token encontrado.

De la descripción anterior se deduce que una secuencia de dos o más bytes delimitadores contiguos en la línea que se escanea se considera un delimitador único y los bytes delimitadores al principio o al final de la cadena se ignoran. En otras palabras, los tokens devueltos strtok() - siempre cadenas no vacías. Es decir, por ejemplo, si hay una línea " aaa;;bbb,", luego llamadas posteriores strtok() con separadores de línea dados " ;, "devolvería las cadenas" aaa" Y " bbb" y luego un puntero nulo.

Función strtok_r() es la versión reentrante strtok(). Argumento guardarptr es un puntero a una variable carácter * que se usa internamente strtok_r() para tener en cuenta el contexto entre llamadas posteriores al analizar la misma cadena.

En primera llamada strtok_r() significado cadena debe apuntar a la cadena que se está analizando y el valor guardarptr ignorado. En llamadas posteriores el valor cadena debe ser NULL y el valor guardarptr no debe cambiar desde la convocatoria anterior.

Se pueden analizar diferentes filas simultáneamente en múltiples ejecuciones strtok_r() con diferentes argumentos guardarptr.

VALOR DEVUELTO

Funciones strtok() Y strtok_r() devuelve un puntero al siguiente token o NULL si no hay más tokens.

ATRIBUTOS

Para obtener una descripción de los términos de esta sección, consulte atributos(7).
Interfaz Atributo Significado
strtok() inofensividad en hilosinseguro (MT-carrera insegura: strtok)
strtok_r() inofensividad en hilosinofensivo (MT-Safe)

CUMPLIMIENTO

strtok() POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD. strtok_r() POSIX.1-2001, POSIX.1-2008.

DEFECTOS

Utilice estas funciones con precaución. Tenga en cuenta que: * Estas funciones modifican su primer argumento. * Estas funciones no se pueden utilizar con cadenas constantes. * Se pierde la identidad del byte separador. * Al analizar la función strtok() utiliza un búfer estático y, por lo tanto, no es seguro para subprocesos. Usar strtok_r() en este caso.

EJEMPLO

El siguiente programa utiliza bucles anidados para llamar strtok_r() para dividir una cadena en sus tokens constituyentes. En el primer parámetro línea de comando Se especifica la cadena a analizar. El segundo parámetro especifica los bytes separadores, que se utilizan para dividir la cadena en tokens "compuestos". El tercer parámetro especifica los bytes separadores, que se utilizan para separar tokens "compuestos" en subtokens.

Ejemplo de salida del programa:

$./a.out "a/bbb///cc;xxx:yyy:" ":;" "/" 1: a/bbb///cc --> a --> bbb --> cc 2: xxx --> xxx 3: yyy --> yyy

Código fuente del programa

#incluir #incluir #incluir int main(int argc, char *argv) ( char *str1, *str2, *token, *subtoken; char *saveptr1, *saveptr2; int j; if (argc != 4) ( fprintf(stderr, "Uso: % s string delim subdelim\n", argv); exit(EXIT_FAILURE); ) for (j = 1, str1 = argv; ; j++, str1 = NULL) ( token = strtok_r(str1, argv, &saveptr1); if (token = = NULL) break; printf("%d: %s\n", j, token); for (str2 = token; ; str2 = NULL) ( subtoken = strtok_r(str2, argv, &saveptr2); if (subtoken == NULL) romper; printf(" --> %s\n", subtoken) ) salir(EXIT_SUCCESS)

Otro ejemplo de un programa que utiliza strtok(), puede encontrarse en getaddrinfo_a(3).

Los lenguajes de programación pueden incluir funciones especiales para trabajar con cadenas, liberando así al programador de la necesidad de escribir sus propias funciones de procesamiento de cadenas. Por ejemplo, a menudo es necesario determinar la longitud de una cadena y, por lo tanto, los idiomas proporcionan una función que mide su longitud.

En el lenguaje de programación C, las funciones para trabajar con cadenas se declaran en el archivo de encabezado string.h, que debes recordar incluir en tu código fuente. Hay unas veinte funciones para trabajar con cadenas. Entre ellas se encuentran las que buscan caracteres en una cadena, funciones de comparación, copia de cadenas, así como otras más específicas. Listado y descripción de los más existentes. este momento Las funciones en el lenguaje C se pueden encontrar en el apéndice del libro de B. Kernighan, D. Ritchie “The C Programming Language Second Edition”.

Todas las funciones declaradas en string.h, durante su trabajo, pueden cambiar o no cambiar una de las cadenas pasadas por el puntero. Depende del propósito de la función. Sin embargo, la mayoría de ellos devuelven algo: un puntero a un carácter o un número entero. Además, si una función cambia uno de sus parámetros y fue llamada para este propósito, entonces lo que devuelve puede ignorarse (es decir, no asignarse a nada en la función que llama).

Por ejemplo, la función strcpy() tiene la siguiente declaración: char *strcpy (char *, const char*) . Copia la cadena a la que apunta el segundo parámetro en la cadena a la que apunta el primer parámetro. De este modo se cambia el primer parámetro. Además, la función devuelve un puntero al primer carácter de la cadena:

carácter s1[ 10 ] , s2[ 10 ] ; carbón * s3; s3 = s2; obtiene(s1); s3 = strcpy(s2, s1); pone (s2); pone (s3); printf("%p, %p \norte", s2, s3);

Aquí s2 y s3 ​​apuntan al mismo símbolo (printf() genera las mismas direcciones). Sin embargo, lo que devuelve strcpy() no se puede asignar a una matriz. El resultado de esta función no suele estar asignado a nada; A veces basta con que simplemente cambie una de las cadenas pasadas por el puntero.

Otra cosa son funciones como strlen() o strcmp() , que no cambian los parámetros, pero se llaman por el resultado. La función strcmp() compara dos cadenas de argumentos letra por letra (lexicográficamente) y devuelve 0, -1 o 1. Por ejemplo, llamar a strcmp("boy", "body") devolverá 1 porque El código de la letra "y" es mayor que el de la letra "d". Llamar a strcmp("body", "boy") devolverá -1 porque el primer argumento es lexicográficamente menor que el segundo.

función strtok()

Mediante el uso funciones strtok() puede dividir una cadena en partes separadas (tokens). La declaración de esta función se ve así: char *strtok (char *, const char *) . Cuando se llama a la función por primera vez, el primer parámetro es la cadena que debe dividirse. El segundo parámetro especifica la cadena separadora. En llamadas posteriores a la función para la misma cadena, el primer parámetro debe ser NULL, porque la función ya ha “recordado” con qué trabaja. Veamos un ejemplo:

char str = "uno, dos, tres, cuatro, cinco"; carbón * sp; sp = strtok (cadena, ", "); mientras (sp) ( pone (sp); sp = strtok (NULL, ", ") ; )

Como resultado de la ejecución de este código, las siguientes palabras se muestran en la pantalla en una columna:

Uno dos tres CUATRO CINCO

La primera vez que se llama a strtok(), se pasa a la función un puntero al primer carácter de la matriz y una cadena delimitadora. Después de esta llamada, la matriz str se cambia, solo queda la palabra "uno" y la función también devuelve un puntero a esta palabra, que se asigna a sp.

Aunque hemos perdido el resto de la matriz en la función de llamada, un puntero al resto de la matriz se almacena dentro de strtok(). Cuando se pasa NULL, la función "sabe" trabajar con esta "cola".

Copiar partes de cadenas

Cuando solo necesitas concatenar dos cadenas, el problema se resuelve fácilmente llamando a la función strcat(), que agrega el segundo argumento al final del primer argumento. Una función similar, strncat(), agrega n caracteres de la segunda cadena a la primera. n se especifica como tercer parámetro.

¿Qué pasa si la situación es más compleja? Por ejemplo, hay dos líneas que no están vacías y es necesario conectar el principio de la primera y el final de la segunda. Esto se puede hacer usando la función strcpy(), si pasas referencias que no sean los primeros caracteres de las líneas:

char s1[ 20 ] = "Peter Smith", s2 = "Julia Roberts"; strcpy (s1+ 5, s2+ 5); pone (s1);

En este caso, aparecerá "Peter Roberts" en la pantalla. ¿Por qué sucedió? Se pasó un puntero al sexto carácter de la primera línea a la función strcpy(). Esto llevó al hecho de que al copiar los caracteres de esta línea se sobrescriben solo a partir del 6, porque strcpy() no "sabe" nada sobre los caracteres anteriores. Solo se pasa también una parte de la cadena como segundo argumento, que se copia al primero.

¿Cómo insertar una línea en medio de otra? Puede resolver este problema usando una tercera línea de “búfer”, donde primero puede copiar la primera línea, luego la segunda, borrando el final de la primera y luego agregando el final de la primera. Pero también puedes hacer esto:

char s1[ 20 ] = "uno tres", s2[ 20 ] = "dos"; strcpy (s2+ 3, s1+ 3); strcpy (s1+ 4, s2); pone (s1);

Aquí, primero se copia el final de la primera en la segunda línea, lo que da como resultado "dos tres". Luego, la segunda línea se copia en la primera, sin pasar por su comienzo.

Descripción de algunas funciones para trabajar con cadenas.

Ejercicio
A continuación se muestran descripciones de algunas funciones que realizan operaciones en cadenas. Diseñe y escriba pequeños programas para ilustrar cómo funcionan estas funciones.

  • char *strchr (const char *, int c). Devuelve un puntero a la primera aparición del carácter c en la cadena. Devuelve NULL si no existe tal carácter en la cadena.
  • char *strstr (const char *s2, const char *s1) . Devuelve un puntero a la primera aparición de la cadena s1 en la cadena s2. Si no hay coincidencias, devuelve NULL.
  • char *strncpy (char *, const char *, size_t n). Copia n caracteres de la segunda línea a la primera.
  • size_t strspn (const char *, const char *) . Devuelve la longitud del comienzo de la primera cadena, que incluye los caracteres que componen la segunda cadena.

Descripción

La función strtok busca tokens en la cadena. Una secuencia de llamadas a esta función divide la cadena en tokens, que son secuencias de caracteres separados por caracteres delimitadores.

En la primera llamada, la función toma como argumento una cadena, cuyo primer carácter se utiliza como punto de partida para la búsqueda de tokens. En llamadas posteriores, la función espera un puntero nulo y utiliza la posición inmediatamente después del final del último token como nueva ubicación para escanear.

Para determinar el comienzo de un token, la función primero determina los caracteres no contenidos en la cadena delim, es decir, son caracteres delimitadores. Y luego verifica el resto de la cadena carácter por carácter hasta el primer carácter delimitador, que señala el final del token.

Este token final se reemplaza automáticamente con un carácter nulo y la función devuelve el token. Después de esto, las llamadas posteriores a la función strtok comienzan con este carácter nulo.

Opciones:

  • cadena
    Una cadena para buscar lexemas. El contenido de esta cadena se cambiará y se dividirá en cadenas más pequeñas (tokens). Este parámetro puede contenerpuntero nulo, en cuyo caso la función continúa escaneando desde donde lo dejó la llamada anterior exitosa a la función.
  • delim
    Una cadena que contiene delimitadores. Pueden variar de una llamada de función a otra llamada de función.

Valor de retorno

Puntero al último token encontrado en la cadena.
Se devuelve un puntero nulo si no se encuentran tokens.

Ejemplo: código fuente del programa

//ejemplo de uso de la función strtok #include #incluir int main () ( char str = "Características de la pesca nacional - largometraje, película de comedia."; std::cout<< "Разделение строки "" << str << "" на лексемы:n"; char * pch = strtok (str," ,.-"); // во втором параметре указаны разделитель (пробел, запятая, точка, тире) while (pch != NULL) // пока есть лексемы { std::cout << pch << "n"; pch = strtok (NULL, " ,.-"); } return 0; }


Arriba