2016-07-01 65 views
6

Mam ten stonowany używany przypadek kodu, który po skompilowaniu z kompilatorem VS 2015 C++ generuje ostrzeżenie.std :: wcstok w 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" "); 
    } 
} 

Wykonano następujące ostrzeżenia.

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' 

Patrząc online, czytałem o std::wcstok i breaking changes in VS 2015 który wspomina, że ​​standard C wprowadzono trzeci parametr i że

Stosowany wewnętrzną, kontekst per-thread śledzić stan całej rozmowy, jak dla strtok. Funkcja ma teraz podpis wchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**) i wymaga, aby wywołujący przekazał kontekst jako trzeci argument funkcji.

Kosztem brzmiące natury głupi, będę nadal iść do przodu i zapytać, Może ktoś proszę wyjaśnić cel tego trzeciego parametru w prostych słowach i jak to się zmieniło std::wcstok z jego wcześniejszej wersji?

+2

na oko, to jest taki sam jak ostatni parametr strtod. Przechowywany jest kolejny element, który można przeanalizować, aby można go było wprowadzić do pierwszego parametru podczas następnego połączenia, co spowodowałoby, że wątek byłby bezpieczny. – cup

+1

Globalny stan CRT to przepis na bardzo paskudne błędy. strtok() jest z pewnością jednym z bardziej złych, errno, strerror(), asctime(), gmtime(), setlocale(), tmpfile(), tmpnam(), fcvt(), ecvt() zasługują na wyróżnienie. –

Odpowiedz

0

Poprzednia wersja była podobna do strtok i używana lokalna pamięć globalna wątków do przechowywania pozycji po zakończeniu ostatniego tokenu.

Problem z zastosowanym podejściem polega na tym, że nie pozwalał na funkcje zagnieżdżania, takie jak strtok/wcstok.

Wyobraź sobie, że mamy ciąg znaków, taki jak "r0c0;r0c1\nr1c0;r1c1" (tabela z 2 rzędami i 2 kolumnami) i chcemy najpierw podzielić go na wiersze, a następnie podzielić każdy wiersz na kolumny.

Do tego potrzebujemy 2 pętli. W starym podejściu jest to niemożliwe, ponieważ pętla zagnieżdżona nadpisałaby stan zewnętrznej pętli. Z nowym podejściu każda pętla może mieć oddzielny stan przechowywane w oddzielnych zmiennych:

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

wyjściowa wynosi:

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