2015-04-14 27 views
13

Questa è la spiegazione di strtok().strtok() - Perché è necessario passare il puntatore NULL per ottenere il token successivo nella stringa?

#include <string.h> 
char* strtok(char* s1, 
       const char* s2);* 

La prima chiamata a strtok() restituisce un puntatore al primo token nella stringa puntato da s1. Le chiamate successive a strtok() devono passare un puntatore NULL come primo argomento, in modo da ottenere il token successivo nella stringa .

Ma non so, perché è necessario passare il puntatore NULL per ottenere il token successivo nella stringa. Ho cercato circa 15 minuti, ma non ho trovato una spiegazione in internet.

+1

Se il codice non ha superato 'null', quello che dovrebbe codice del passaggio di continuare creazione di token la stessa stringa ? – chux

+0

Suppongo che sia solo così che puoi disattivare la tokenizzazione dell'intera stringa contemporaneamente senza tenere traccia di dove iniziare il prossimo token tu stesso. Se questo è stato progettato in C++ in questo momento, molto probabilmente sarebbe diverso. – chris

+1

Non hai visto http://www.cplusplus.com/reference/cstring/strtok/ nella tua ricerca? – usr2564301

risposta

24

strtok() conserva alcuni dati in variabili statiche all'interno della funzione stessa in modo che possa continuare una ricerca dal punto in cui ha lasciato la chiamata precedente. Per segnalare strtok() che si desidera continuare a cercare la stessa stringa, si passa un puntatore NULL come primo argomento. strtok() controlla se è NULL e se è così, utilizza i dati attualmente memorizzati. Se il primo parametro non è nullo, viene considerato come una nuova ricerca e tutti i dati interni vengono reimpostati.

Forse la cosa migliore che puoi fare è cercare un'implementazione effettiva della funzione strtok(). Ho trovato un piccolo abbastanza per postare qui, in modo da avere un'idea di come gestire questo parametro NULL:

/* Copyright (c) Microsoft Corporation. All rights reserved. */ 

#include <string.h> 

/* ISO/IEC 9899 7.11.5.8 strtok. DEPRECATED. 
* Split string into tokens, and return one at a time while retaining state 
* internally. 
* 
* WARNING: Only one set of state is held and this means that the 
* WARNING: function is not thread-safe nor safe for multiple uses within 
* WARNING: one thread. 
* 
* NOTE: No library may call this function. 
*/ 

char * __cdecl strtok(char *s1, const char *delimit) 
{ 
    static char *lastToken = NULL; /* UNSAFE SHARED STATE! */ 
    char *tmp; 

    /* Skip leading delimiters if new string. */ 
    if (s1 == NULL) { 
     s1 = lastToken; 
     if (s1 == NULL)   /* End of story? */ 
      return NULL; 
    } else { 
     s1 += strspn(s1, delimit); 
    } 

    /* Find end of segment */ 
    tmp = strpbrk(s1, delimit); 
    if (tmp) { 
     /* Found another delimiter, split string and save state. */ 
     *tmp = '\0'; 
     lastToken = tmp + 1; 
    } else { 
     /* Last segment, remember that. */ 
     lastToken = NULL; 
    } 

    return s1; 
} 
+4

Grazie mille, ora lo capisco! – phez1

+0

* AVVISO: viene trattenuto solo un set di stato e ciò significa che la funzione * WARNING: non è protetta da thread né sicura per più utilizzi all'interno di * AVVERTENZA: un thread. Cosa significa? –

+0

@MinhTran Significa che questa funzione non deve essere utilizzata nella chiamata multi-thread perché la variabile statica può essere cambiata da un altro thread. Vedi "/ * UNSAFE SHARED STATE! */' – thangdc94

7

Se si passa un valore non NULL, si sta chiedendo di iniziare a tokenizzare una stringa diversa.

Se si passa un valore NULL, si chiede di continuare a tokenizzare la stessa cosa di prima.

+1

Ma come fa lo strtok a sapere che è la stessa stringa? Ora si passa NULL, ma questo non è l'indirizzo della stringa. – phez1

+4

@ ezph1, gestisce solo una stringa alla volta e mantiene lo stato interno, il che causa tutti i tipi di problemi. – chris