Usando strtok em c

Eu preciso usar strtok para ler em um primeiro e último nome e separá-lo. Como posso armazenar os nomes onde posso usá-los de forma independente em dois arranjos de caracteres separados?

#include  #include  int main () { char str[] ="test string."; char * test; test = strtok (str," "); while (test != NULL) { printf ("%s\n",test); test= strtok (NULL, " "); } return 0; } 

Aqui está a minha opinião sobre um ajudante tokenize razoavelmente simples que

  • armazena resultados em um array dinamicamente crescente
  • terminação nula da matriz
  • mantém a string de input segura (strtok modifica a string de input, que é o comportamento indefinido em um char literal [], pelo menos eu acho em C99)

Para tornar o código reentrante, use o strtok_r não padrão

 #include  #include  #include  char** tokenize(const char* input) { char* str = strdup(input); int count = 0; int capacity = 10; char** result = malloc(capacity*sizeof(*result)); char* tok=strtok(str," "); while(1) { if (count >= capacity) result = realloc(result, (capacity*=2)*sizeof(*result)); result[count++] = tok? strdup(tok) : tok; if (!tok) break; tok=strtok(NULL," "); } free(str); return result; } int main () { char** tokens = tokenize("test string."); char** it; for(it=tokens; it && *it; ++it) { printf("%s\n", *it); free(*it); } free(tokens); return 0; } 

Aqui está uma reimplementação de strtok free de que (usa strpbrk vez):

 char** tokenize(const char* str) { int count = 0; int capacity = 10; char** result = malloc(capacity*sizeof(*result)); const char* e=str; if (e) do { const char* s=e; e=strpbrk(s," "); if (count >= capacity) result = realloc(result, (capacity*=2)*sizeof(*result)); result[count++] = e? strndup(s, es) : strdup(s); } while (e && *(++e)); if (count >= capacity) result = realloc(result, (capacity+=1)*sizeof(*result)); result[count++] = 0; return result; } 

Você precisa armazená-los separadamente? Dois pointers em uma matriz char modificada produzirão duas strings separadas perfeitamente utilizáveis.

Isso é que nós transformamos isso:

 char str[] ="test string."; 

Nisso:

 char str[] ="test\0string."; ^ ^ | | char *s1 ----- | char *s2 ----------- 

.

 #include  #include  int main () { char str[] ="test string."; char *firstname = strtok(str, " "); char *lastname = strtok(NULL, " "); if (!lastname) lastname = ""; printf("%s, %s\n", lastname, firstname); return 0; } 

Que tal usar strcpy :

 #include  #include  #include  #define MAX_NAMES 2 int main () { char str[] ="test string."; char *names[MAX_NAMES] = { 0 }; char *test; int i = 0; test = strtok (str," "); while (test != NULL && i < MAX_NAMES) { names[i] = malloc(strlen(test)+1); strcpy(names[i++], test); test = strtok (NULL, " "); } for(i=0; i 

Ele contém muita confusão para manter um programa completo e limpar seus resources, mas o ponto principal é usar o strcpy para copiar cada token em sua própria string.

 #include  #include  #include  char** split(const char *str, const char *delimiter, size_t *len){ char *text, *p, *first, **array; int c; char** ret; *len = 0; text=strdup(str); if(text==NULL) return NULL; for(c=0,p=text;NULL!=(p=strtok(p, delimiter));p=NULL, c++)//count item if(c==0) first=p; //first token top ret=(char**)malloc(sizeof(char*)*c+1);//+1 for NULL if(ret==NULL){ free(text); return NULL; } strcpy(text, str+(first-text));//skip until top token array=ret; for(p=text;NULL!=(p=strtok(p, delimiter));p=NULL){ *array++=p; } *array=NULL; *len=c; return ret; } void free4split(char** sa){ char **array=sa; if(sa!=NULL){ free(array[0]);//for text free(sa); //for array } } int main(void){ char str[] ="test string."; char **words; size_t len=0; int i; words = split(str, " \t\r\n,.", &len); /* for(char **wk = words; *wk ;wk++){ printf("%s\n", *wk); } */ for(i = 0;i 

Copie os resultados do strtok para um novo buffer usando uma function como

 /* * Returns a copy of s in freshly allocated memory. * Exits the process if memory allocation fails. */ char *xstrdup(char const *s) { char *p = malloc(strlen(s) + 1); if (p == NULL) { perror("memory allocation failed"); exit(1); } strcpy(p, s); return p; } 

Não se esqueça de free os valores de retorno quando terminar com eles.

IMO, você não precisa (e provavelmente não quer) usar strtok (como em “para isso, ou muito de qualquer outra coisa”). Eu acho que eu usaria um código como este:

 #include  #include  static char *make_str(char const *begin, char const *end) { size_t len = end-begin; char *ret = malloc(len+1); if (ret != NULL) { memcpy(ret, begin, len); ret[len]='\0'; } return ret; } size_t tokenize(char *tokens[], size_t max, char const *input, char const *delims) { int i; char const *start=input, *end=start; for (i=0; *start && i 

Você pode fazer algo assim também.

  int main () { char str[] ="test string."; char * temp1; char * temp2; temp1 = strtok (str," "); temp2 = strchr(str, ' '); if (temp2 != NULL) temp2++; printf ("Splitted string :%s, %s\n" , temp1 , temp2); return }