Por favor, me explique o funcionamento da strtok()
função. O manual diz que divide a string em tokens. Não consigo entender com base no manual o que ele realmente faz.
Eu adicionei watch on str
e *pch
para verificar seu funcionamento quando o primeiro loop while ocorreu, o conteúdo de str
era apenas "this". Como a saída mostrada abaixo foi impressa na tela?
/* strtok example */
#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;
}
Resultado:
Dividindo string "- Este, um string de amostra." em tokens: este uma amostra corda
strtok()
modifica sua string de argumento encerrando tokens com NUL antes de retornar. Se você tentar examinar todo o buffer (str []), você o verá sendo modificado entre chamadas sucessivas destrtok()
.str
, relógiostr[0]
,str[1]
,str[2]
, ...Respostas:
strtok()
divide a string em tokens. ou seja, começar de qualquer um dos delimitadores para o próximo seria seu único token. No seu caso, o token inicial será de "-" e terminará com o próximo espaço "". O próximo token começará em "" e terminará com ",". Aqui você obtém "This" como saída. Da mesma forma, o resto da string é dividido em tokens de espaço para espaço e, finalmente, terminando o último token em "."fonte
a função de tempo de execução strtok funciona assim
na primeira vez que você chama strtok, você fornece uma string que deseja tokenizar
no espaço da string acima parece ser um bom delimitador entre as palavras, então vamos usar isso:
o que acontece agora é que 's' é pesquisado até que o caractere de espaço seja encontrado, o primeiro token é retornado ('this') e p aponta para esse token (string)
a fim de obter o próximo token e continuar com a mesma string, NULL é passado como primeiro argumento, pois strtok mantém um ponteiro estático para a string passada anterior:
p agora aponta para 'é'
e assim por diante até que nenhum outro espaço seja encontrado, então a última string é retornada como o último token 'string'.
mais convenientemente, você poderia escrever assim em vez de imprimir todos os tokens:
EDITAR:
Se você deseja armazenar os valores retornados,
strtok
você precisa copiar o token para outro buffer, por exemplo,strdup(p);
já que a string original (apontada pelo ponteiro estático dentrostrtok
) é modificada entre as iterações para retornar o token.fonte
p
aponta para aquele token" , é questrtok
precisa alterar a string original colocando um caractere nulo no lugar de um delimitador (caso contrário, outras funções de string não saberiam onde o token termina). E também rastreia o estado usando uma variável estática.strtok
mantém uma referência interna estática apontando para o próximo token disponível na string; se você passar um ponteiro NULL, ele funcionará a partir dessa referência interna.Esta é a razão pela qual
strtok
não é reentrante; assim que você passa um novo ponteiro, aquela referência interna antiga é eliminada.fonte
strtok
não muda o próprio parâmetro (str
). Ele armazena esse ponteiro (em uma variável estática local). Ele pode então alterar o que esse parâmetro aponta nas chamadas subsequentes sem que o parâmetro seja passado de volta. (E ele pode avançar esse ponteiro que manteve, da maneira que for necessário para realizar suas operações.)Na
strtok
página POSIX :Existe uma variante thread-safe (
strtok_r
) que não faz esse tipo de mágica.fonte
ctime
retornar uma string estática - prática (ninguém precisa se perguntar quem deve liberá-la), mas não reentrar e tropeçar em você se você não estiver muito ciente disso.strtok
não altera o próprio parâmetro (str
)."puts(str);
imprime "- This" desdestrtok
modificadostr
.Na primeira vez que você chama, você fornece a string para tokenizar
strtok
. E então, para obter os seguintes tokens, basta darNULL
a essa função, desde que ela retorne um nãoNULL
ponteiro.A
strtok
função registra a string que você forneceu primeiro ao chamá-la. (O que é realmente perigoso para aplicativos multi-thread)fonte
strtok irá tokenizar uma string, isto é, convertê-la em uma série de substrings.
Ele faz isso procurando por delimitadores que separam esses tokens (ou substrings). E você especifica os delimitadores. No seu caso, você quer '' ou ',' ou '.' ou '-' para ser o delimitador.
O modelo de programação para extrair esses tokens é que você entrega ao strtok sua string principal e o conjunto de delimitadores. Em seguida, você o chama repetidamente e, a cada vez, strtok retornará o próximo token que encontrar. Até atingir o final da string principal, quando retorna um nulo. Outra regra é que você passe a string apenas na primeira vez e NULL nas vezes subsequentes. Esta é uma maneira de dizer a strtok se você está iniciando uma nova sessão de tokenização com uma nova string ou se está recuperando tokens de uma sessão de tokenização anterior. Observe que strtok lembra seu estado para a sessão de tokenização. E por esta razão não é reentrante ou thread-safe (você deve usar strtok_r ao invés). Outra coisa a saber é que ele realmente modifica a string original. Ele escreve '\ 0' para os delimitadores que encontrar.
Uma maneira de invocar strtok, sucintamente, é a seguinte:
Resultado:
fonte
strtok modifica sua string de entrada. Ele coloca caracteres nulos ('\ 0') nele para que retorne bits da string original como tokens. Na verdade, strtok não aloca memória. Você pode entender melhor se desenhar o barbante como uma sequência de caixas.
fonte
Para entender como
strtok()
funciona, primeiro é necessário saber o que é uma variável estática . Este link explica muito bem ....A chave para a operação de
strtok()
é preservar a localização do último separador entre chamadas seccessivas (é por isso questrtok()
continua a analisar a string original que é passada para ele quando é invocado comnull pointer
chamadas sucessivas).Dê uma olhada em minha própria
strtok()
implementação, chamadazStrtok()
, que tem uma funcionalidade ligeiramente diferente da fornecida porstrtok()
E aqui está um exemplo de uso
O código é de uma biblioteca de processamento de strings que mantenho no Github , chamada zString. Dê uma olhada no código ou até mesmo contribua :) https://github.com/fnoyanisi/zString
fonte
Foi assim que implementei o strtok, não muito bom, mas depois de trabalhar 2 horas nele, finalmente consegui funcionar. Ele oferece suporte a vários delimitadores.
fonte
strtok substitui os caracteres no segundo argumento por um caractere NULL e um caractere NULL também é o fim de uma string.
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
fonte
Aqui está minha implementação que usa uma tabela hash para o delimitador, o que significa O (n) em vez de O (n ^ 2) (aqui está um link para o código) :
fonte
strtok () armazena o ponteiro na variável estática onde você parou da última vez, então em sua segunda chamada, quando passamos o nulo, strtok () obtém o ponteiro da variável estática.
Se você fornecer o mesmo nome de string, ele começará novamente do início.
Além disso, strtok () é destrutivo, ou seja, faz alterações na string original. portanto, certifique-se de sempre ter uma cópia do original.
Outro problema de usar strtok () é que, como ele armazena o endereço em variáveis estáticas, na programação multithread chamar strtok () mais de uma vez causará um erro. Para isso, use strtok_r ().
fonte
Para aqueles que ainda estão com dificuldades para entender esta
strtok()
função, dê uma olhada neste exemplo do pythontutor , é uma ótima ferramenta para visualizar seu código C (ou C ++, Python ...).Caso o link tenha quebrado, cole:
Os créditos vão para Anders K.
fonte
você pode escanear o array char procurando pelo token se você o encontrou apenas imprima uma nova linha senão imprima o char.
fonte
Portanto, este é um trecho de código para ajudar a entender melhor este tópico.
Impressão de tokens
Tarefa: dada uma frase, s, imprima cada palavra da frase em uma nova linha.
Entrada:
How is that
Resultado:
Explicação: Então, aqui, a função "strtok ()" é usada e iterada usando o loop for para imprimir os tokens em linhas separadas.
A função pegará parâmetros como 'string' e 'break-point' e quebrará a string nesses pontos de quebra e formará tokens. Agora, esses tokens são armazenados em 'p' e são usados posteriormente para impressão.
fonte