¿Por qué strtok cambia su entrada de esta manera?

4 minutos de lectura

Ok, entiendo que strtok modifica su argumento de entrada, pero en este caso, colapsa la cadena de entrada en solo el primer token. ¿Por qué sucede esto y qué puedo hacer para solucionarlo? (Tenga en cuenta que no estoy hablando de la variable “temp”, que deberían ser el primer token, sino la variable “entrada”, que después de una llamada a strtok se convierte en “esto”)

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[]) {
   char input[]="this is a test of the tokenizor seven";
   char * temp;
   temp=strtok(input," ");
   printf("input: %s\n", input); //input is now just "this"
}

Cuándo strtok() encuentra una ficha, cambia el carácter inmediatamente después de la ficha en un \0y luego devuelve un puntero al token. La próxima vez que lo llame con un NULL argumento, comienza a buscar los separadores que terminaron el primer token, es decir, después del \0y posiblemente más adelante.

Ahora, el puntero original al comienzo de la cadena aún apunta al comienzo de la cadena, pero el primer token ahora es \0-terminado — es decir, printf() piensa que el final del token es el final de la cadena. El resto de los datos sigue ahí, pero eso \0 se detiene printf() de mostrarlo. Si usaste un for-loop para recorrer la cadena de entrada original hasta el número original de caracteres, encontraría que todos los datos todavía están allí.

  • Oh ya veo. Mi comprensión de cómo funciona strtok estaba muy lejos: asumí que mordió el token y luego deslicé el puntero de entrada al primer carácter después del delimitador. En cualquier caso, ¡gracias! Esta fue una respuesta muy clara y útil.

    – usuario1209326

    23 de febrero de 2012 a las 3:12

  • Pero después strtok termina y devuelve NULL (ya que no hay más tokens), se restaura la cadena inicial? O con el fin de utilizar con seguridad el strtok deberías hacer una copia de la cadena de origen? Además, ¿qué pasará con mi cadena original si detengo el strtok antes de que finalice?

    – Catalina Sirbu

    30 de diciembre de 2020 a las 19:32


  • @CătălinaSîrbu Si necesita conservar el contenido original del búfer de caracteres, entonces sí, necesitaría hacer una copia. Pero en la práctica ese es raramente el caso.

    – Ernest Friedman-Hill

    30 de diciembre de 2020 a las 19:37

  • Necesitaría una aclaración más, estaba leyendo esto Se debe hacer una observación muy importante aquí: la función modifica la cadena a la que apunta el primer argumento (coloca caracteres nulos al final de los tokens, pero todos se eliminarán después de la última invocación). Por lo que entiendo, esto es incorrecto, la cadena de origen no ser restaurado después de la última invocación de strtok (es decir, la invocación que devolverá NULL). Es tan ?

    – Catalina Sirbu

    30 de diciembre de 2020 a las 19:50


  • @CătălinaSîrbu Sí, esa cita (¿de dónde es?) es incorrecta. strtok no restaura la cadena original bajo ninguna circunstancia. Si lo hiciera, invalidaría todos los tokens que había creado, lo que significa que tendría que copiarlos para que fueran útiles, lo cual no es el caso.

    – Ernest Friedman-Hill

    30 de diciembre de 2020 a las 19:57

Debe imprimir el token que recibe de strtok y no se preocupe por la matriz de entrada porque los NULL serán insertados por strtok. Necesita llamadas repetidas para obtener todos los tokens:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[]) {
  char input[]="this is a test of the tokenizor seven";
  char * temp;
  temp=strtok(input," ");
  while( temp != NULL ) {
    printf("temp is \"%s\"\n", temp );
    temp = strtok( NULL, " ");
  }
}

  • Como dije anteriormente, claramente tenía una idea equivocada de cómo strtok realmente tokenizaba las cosas. ¡Gracias por tu ayuda!

    – usuario1209326

    23 de febrero de 2012 a las 3:18

Es porque strtok inserta valores nulos en cada separador, razón por la cual usa llamadas repetidas a strtok para obtener cada token. La cadena de entrada no se puede usar una vez que comience a usar strtok. No lo “arreglas”, así es como funciona.

  • Gracias por una respuesta tan rápida. Por supuesto, cuando dije “arréglalo”, quise decir “¿cómo obtengo el resultado que deseo?”, pero agradezco que te tomes el tiempo para ayudarme.

    – usuario1209326

    23 de febrero de 2012 a las 3:16

  • Si necesita una copia no afectada de la cadena de entrada, debe hacer una copia antes de ejecutar strtok.

    – José

    23 de febrero de 2012 a las 12:11

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad