Tokenización de cadenas en C

He intentado tokenizar una cadena usando SPACE como delimitador, pero no funciona. ¿Alguien tiene alguna sugerencia sobre por qué no funciona?

Editar: tokenización usando:

strtok(string, " "); 

El código es como el siguiente

 pch = strtok (str," "); while (pch != NULL) { printf ("%s\n",pch); pch = strtok (NULL, " "); } 

Hazlo asi:

 char s[256]; strcpy(s, "one two three"); char* token = strtok(s, " "); while (token) { printf("token: %s\n", token); token = strtok(NULL, " "); } 

Nota: strtok modifica la cadena su tokenización, por lo que no puede ser un const char* .

Aquí hay un ejemplo del uso de strtok , tenga en cuenta que strtok es destructivo para su cadena de entrada (y por lo tanto no puede ser usado en una constante de cadena)

 char *p = strtok(str, " "); while(p != NULL) { printf("%s\n", p); p = strtok(NULL, " "); } 

Básicamente, lo que hay que tener en cuenta es que pasar un NULL como el primer parámetro a strtok le dice que obtenga el siguiente token de la cadena que previamente estaba tokenizando.

strtok puede ser muy peligroso. No es seguro para subprocesos. Su uso previsto debe ser repetido una y otra vez en un bucle, pasando el resultado de la llamada anterior. La función strtok tiene una variable interna que almacena el estado de la llamada strtok. Este estado no es exclusivo de cada hilo: es global. Si cualquier otro código usa strtok en otro hilo, obtienes problemas. ¡No es el tipo de problemas que quieres rastrear tampoco!

Recomiendo buscar una implementación de expresiones regulares o usar sscanf para separar la cadena.

Prueba esto:

 char strprint[256]; char text[256]; strcpy(text, "My string to test"); while ( sscanf( text, "%s %s", strprint, text) > 0 ) { printf("token: %s\n", strprint); } 

Nota: La cadena ‘texto’ se destruye a medida que se separa. Esta puede no ser la conducta preferida =)

Puede simplificar el código introduciendo una variable adicional.

 #include  #include  int main() { char str[100], *s = str, *t = NULL; strcpy(str, "a space delimited string"); while ((t = strtok(s, " ")) != NULL) { s = NULL; printf(":%s:\n", t); } return 0; } 

He hecho algunas funciones de cadena para dividir valores, utilizando menos punteros como pude porque este código está destinado a ejecutarse en procesadores PIC18F. Esos procesadores no se manejan muy bien con punteros cuando tienes poca RAM libre disponible:

 #include  #include  char POSTREQ[255] = "pwd=123456&apply=Apply&d1=88&d2=100&pwr=1&mpx=Internal&stmo=Stereo&proc=Processor&cmp=Compressor&ip1=192&ip2=168&ip3=10&ip4=131&gw1=192&gw2=168&gw3=10&gw4=192&pt=80&lic=&A=A"; int findchar(char *string, int Start, char C) { while((string[Start] != 0)) { Start++; if(string[Start] == C) return Start; } return -1; } int findcharn(char *string, int Times, char C) { int i = 0, pos = 0, fnd = 0; while(i < Times) { fnd = findchar(string, pos, C); if(fnd < 0) return -1; if(fnd > 0) pos = fnd; i++; } return fnd; } void mid(char *in, char *out, int start, int end) { int i = 0; int size = end - start; for(i = 0; i < size; i++){ out[i] = in[start + i + 1]; } out[size] = 0; } void getvalue(char *out, int index) { mid(POSTREQ, out, findcharn(POSTREQ, index, '='), (findcharn(POSTREQ, index, '&') - 1)); } void main() { char n_pwd[7]; char n_d1[7]; getvalue(n_d1, 1); printf("Value: %s\n", n_d1); } 

Al leer la documentación de strtok, veo que necesita pasar un puntero NULL después de la primera llamada de “inicialización”. Quizás no hiciste eso. Solo una conjetura, por supuesto.

Aquí hay otra implementación de strtok() , que tiene la capacidad de reconocer delimitadores consecutivos ( strtok() la biblioteca estándar no tiene esto)

La función es una parte de la biblioteca de cadenas con licencia de BSD, llamada zString . Eres más que bienvenido a contribuir 🙂

https://github.com/fnoyanisi/zString

 char *zstring_strtok(char *str, const char *delim) { static char *static_str=0; /* var to store last address */ int index=0, strlength=0; /* integers for indexes */ int found = 0; /* check if delim is found */ /* delimiter cannot be NULL * if no more char left, return NULL as well */ if (delim==0 || (str == 0 && static_str == 0)) return 0; if (str == 0) str = static_str; /* get length of string */ while(str[strlength]) strlength++; /* find the first occurance of delim */ for (index=0;index 

Como mencioné en publicaciones anteriores, dado que strtok() , o el que implementé anteriormente, depende de una variable static *char para conservar la ubicación del último delimitador entre llamadas consecutivas, se debe tener especial cuidado al tratar con aplicaciones de subprocesos múltiples.

 int not_in_delimiter(char c, char *delim){ while(*delim != '\0'){ if(c == *delim) return 0; delim++; } return 1; } char *token_separater(char *source, char *delimiter, char **last){ char *begin, *next_token; char *sbegin; /*Get the start of the token */ if(source) begin = source; else begin = *last; sbegin = begin; /*Scan through the string till we find character in delimiter. */ while(*begin != '\0' && not_in_delimiter(*begin, delimiter)){ begin++; } /* Check if we have reached at of the string */ if(*begin == '\0') { /* We dont need to come further, hence return NULL*/ *last = NULL; return sbegin; } /* Scan the string till we find a character which is not in delimiter */ next_token = begin; while(next_token != '\0' && !not_in_delimiter(*next_token, delimiter)) { next_token++; } /* If we have not reached at the end of the string */ if(*next_token != '\0'){ *last = next_token--; *next_token = '\0'; return sbegin; } } void main(){ char string[10] = "abcb_dccc"; char delim[10] = "_"; char *token = NULL; char *last = "" ; token = token_separater(string, delim, &last); printf("%s\n", token); while(last){ token = token_separater(NULL, delim, &last); printf("%s\n", token); } 

}

Puedes leer el análisis detallado en el blog mencionado en mi perfil 🙂