2016-07-01 5 views
6

У меня этот тонированный использованный код кода, который при компиляции с компилятором VS 2015 C++ выдает предупреждение.std :: wcstok в 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" "); 
    } 
} 

Это привело к следующим предупреждениям.

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' 

Глядя в Интернете, я читал о std::wcstok и breaking changes in VS 2015, который отмечает, что стандарт C ввел третий параметр и что

Он используется внутренний, для каждого треда контекста для отслеживания состояния между вызовами, как делается для strtok. Функция теперь имеет подпись wchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**) и требует, чтобы вызывающий абонент передал контекст в качестве третьего аргумента функции.

Цены звучащего по своей сути глупо, я все равно буду идти вперед и спросить, Может кто-нибудь, пожалуйста, объясните цель этого третьего параметра в простых терминах, и как она изменилась std::wcstok от его предыдущей версии?

+2

На догадке, он такой же, как последний параметр strtod. Он удерживает следующий элемент для анализа, поэтому его можно передать в первый параметр при следующем вызове, который сделает его потокобезопасным. – cup

+1

Глобальное состояние CRT - это рецепт для очень неприятных ошибок. strtok(), безусловно, является одним из наиболее злых, errno, strerror(), asctime(), gmtime(), setlocale(), tmpfile(), tmpnam(), fcvt(), ecvt() заслуживают почетного упоминания. –

ответ

0

Старая версия была похожа на strtok и использовала локальное хранилище глобальной нити для хранения позиции за конец последнего токена.

Проблема с используемым подходом заключается в том, что он не разрешает функции вложенности, такие как strtok/wcstok.

Представьте себе, что у нас есть строка, как "r0c0;r0c1\nr1c0;r1c1" (таблица с двумя строками и двумя столбцами), и мы хотим сначала разбить ее на строки, а затем разбить каждую строку на столбцы.

Для этого нам нужно 2 петли. При использовании старого подхода это невозможно, так как вложенный цикл будет перезаписывать состояние внешнего цикла. При новом подходе каждый цикл может иметь отдельное состояние, хранящееся в отдельном переменных:

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

Выхода:

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

 Смежные вопросы

  • Нет связанных вопросов^_^