2016-07-01 29 views
6

Ho questo caso di codice usato che, compilato con il compilatore C++ di VS 2015, genera un avviso.std :: wcstok in VS 2015

#include <cwchar> 
#include <iostream> 

int main() 
{ 
    wchar_t input[100] = L"A bird came down the walk"; 
    wchar_t* token = std::wcstok(input, L" "); 
    while (token) { 
     std::wcout << token << '\n'; 
     token = std::wcstok(nullptr, L" "); 
    } 
} 

Questo prodotto ha generato le seguenti avvertenze.

warning C4996: 'wcstok': wcstok has been changed to conform with the ISO C standard, adding an extra context parameter. To use the legacy Microsoft wcstok, define _CRT_NON_CONFORMING_WCSTOK. 
1> c:\program files (x86)\windows kits\10\include\10.0.10240.0\ucrt\corecrt_wstring.h(254): note: see declaration of 'wcstok' 

warning C4996: 'wcstok': wcstok has been changed to conform with the ISO C standard, adding an extra context parameter. To use the legacy Microsoft wcstok, define _CRT_NON_CONFORMING_WCSTOK. 
1> c:\program files (x86)\windows kits\10\include\10.0.10240.0\ucrt\corecrt_wstring.h(254): note: see declaration of 'wcstok' 

Alzando gli occhi in linea, ho letto di std::wcstok e breaking changes in VS 2015 che menziona che il C di serie ha introdotto un terzo parametro e che

E 'utilizzato un, per-filo contesto interno per monitorare lo stato tra chiamate, come per lo strtok. La funzione ha ora la firma wchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**) e richiede al chiamante di passare il contesto come terzo argomento alla funzione.

A costo di sembrare intrinsecamente stupido, lo sarà ancora andare avanti e chiedere, Qualcuno può spiegare lo scopo di questo terzo parametro in termini semplici e come è cambiato std::wcstok dalla sua versione precedente?

+2

A occhio e croce, è la stessa come ultimo parametro di strtod. Tiene il prossimo oggetto da analizzare in modo che questo possa essere inserito nel primo parametro della prossima chiamata, il che lo renderebbe sicuro. – cup

+1

Lo stato CRT globale è una ricetta per i bug molto cattivi. strtok() è sicuramente uno dei più malvagi, errno, strerror(), asctime(), gmtime(), setlocale(), tmpfile(), tmpnam(), fcvt(), ecvt() meritano una menzione d'onore. –

risposta

0

La versione precedente era simile a strtok e utilizzata la memoria locale del thread globale per archiviare la posizione oltre la fine dell'ultimo token.

Il problema dell'approccio utilizzato è che non consente funzioni di nidificazione come strtok/wcstok.

Immaginate di avere una stringa come "r0c0;r0c1\nr1c0;r1c1" (una tabella con 2 righe e 2 colonne) e vogliamo dividerla prima in righe, quindi dividere ogni riga in colonne.

Per fare ciò sono necessari 2 cicli. Con il vecchio approccio questo è impossibile, poiché il ciclo annidato sovrascrive lo stato del ciclo esterno. Con il nuovo approccio ogni ciclo può avere uno stato separato conservato in un variabili distinte:

#include <cwchar> 
#include <iostream> 

int main() 
{ 
    wchar_t input[] = L"r0c0;r0c1\n" 
         L"r1c0;r1c1"; 
    wchar_t *rowstate; 
    wchar_t *row = std::wcstok(input, L"\n", &rowstate); 

    while (row != nullptr) { 
     std::wcout << L"Row: " << row << std::endl; 

     wchar_t *colstate; 
     wchar_t *col = std::wcstok(row, L";", &colstate); 

     while (col != nullptr) { 
      std::wcout << " Col: " << col << std::endl; 
      col = std::wcstok(nullptr, L" ", &colstate); 
     } 

     row = std::wcstok(nullptr, L" ", &rowstate); 
    } 
} 

uscita è:

Row: r0c0;r0c1 
    Col: r0c0 
    Col: r0c1 
Row: r1c0;r1c1 
    Col: r1c0 
    Col: r1c1 
Problemi correlati