2016-07-01 12 views
6

Ich habe diese abgeschwächten verwendeten Fall von Code, der, wenn mit VS 2015 C++ Compiler kompiliert eine Warnung erstellt.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" "); 
    } 
} 

Dies ergab folgende Warnungen.

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' 

Online Aufblickend Ich las über std::wcstok und breaking changes in VS 2015, die erwähnt, dass C-Standard einen dritten Parameter eingeführt hat und dass

Es verwendet einen internen, pro Thread Kontextzustand über Anrufe zu verfolgen, wie für Strtok getan. Die Funktion hat nun die Signatur wchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**) und fordert den Aufrufer auf, den Kontext als drittes Argument an die Funktion zu übergeben.

Auf Kosten der Sondierung von Natur aus dumm, ich werde noch vor ihnen und fragen gehen, Kann jemand bitte den Zweck dieses dritten Parameters in einfachen Worten erklären und wie es std::wcstok aus seiner früheren Version geändert hat?

+2

Bei einer Vermutung, es ist die gleiche wie der letzte Parameter von strtod ist. Es enthält das nächste Element, das geparst werden soll, damit es beim nächsten Aufruf in den ersten Parameter eingegeben werden kann, wodurch es threadsicher wird. – cup

+1

Der globale CRT-Status ist ein Rezept für sehr unangenehme Fehler. strtok() ist sicherlich einer der böseren, errno, strerror(), asctime(), gmtime(), setlocale(), tmpfile(), tmpnam(), fcvt(), ecvt() verdienen eine ehrenvolle Erwähnung. –

Antwort

0

Ältere Version war vergleichbar mit strtok und verwendet globalen Thread lokalen Speicher zum Speichern der Position nach dem Ende des letzten Token.

Das Problem mit dem verwendeten Ansatz ist, dass es keine Verschachtelungsfunktionen wie strtok/wcstok erlaubt.

Stellen Sie sich vor, wir haben eine Zeichenfolge wie "r0c0;r0c1\nr1c0;r1c1" (eine Tabelle mit 2 Zeilen und 2 Spalten) und wir möchten es zuerst in Zeilen aufteilen und dann jede Zeile in Spalten aufteilen.

Dazu benötigen wir 2 Schleifen. Mit dem alten Ansatz ist dies unmöglich, da die verschachtelte Schleife den Zustand der äußeren Schleife überschreiben würde. Mit neuem Ansatz kann jede Schleife einen eigenen Staat in einer separaten Variablen gespeichert hat:

#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); 
    } 
} 

Ausgang ist:

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