2010-11-10 58 views
1

C運行時區域設置由setlocale設置。 的標準C++庫(STL)區域設置由std::locale類設置,並且可以在個體對象STL比如std :: istringstream等被設置當使用_ENABLE_PER_THREAD_LOCALE時,STL對象使用C運行時庫語言環境進行浮點轉換?

功能_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)允許設置在每個線程的基礎上C運行區域設置。

不幸的是,啓用了_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)的線程中的STL對象似乎正在使用C運行時區域設置。或者至少使用C運行時語言環境的小數點。

在沒有_ENABLE_PER_THREAD_LOCALE的線程中沒有問題。類似

東西在2008年被要求帕沃,但沒有答案:_configthreadlocale and localeconv

下面的代碼顯示問題:

//Enable per thread locale in current thread 
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE) 

//Create istringstream object 
std::istringstream LibraryStream; 
//Create double object 
double Value = 0; 
//Create std::locale object with "C" locale ("." as decimal point) 
std::locale StreamLoc("C"); 
//Set C Runtime locale to danish ("," as decimal point) 
setlocale(LC_ALL, "danish"); 

//Set the "C" locale on the istringstream object 
LibraryStream.imbue(StreamLoc); 
//Get the locale of the istringstream object for test (returns "C" as expected) 
std::locale NewStreamLoc = LibraryStream.getloc(); 

//Set floating point string with "C" locale decimal point in istringstream object 
LibraryStream.str("60.258351"); 
//Convert the string to double 
LibraryStream >> Value; 

//Now the expected value of "Value" is 60.258351, but it is 60.000 
//when debugging the conversion, I can see that "," is used as decimal point 

有任何人經歷過這個?難道我做錯了什麼?有沒有解決方案的建議?

在此先感謝 /TEB

+0

歡迎SO。在發佈代碼示例時,您可以使用編輯字段上方的小'101101'按鈕來正確獲取代碼格式。 – 2010-11-10 14:56:23

+0

謝謝,我會記住的。 – TEB 2010-11-10 14:58:13

回答

3

由於C++標準庫只有最近獲得了線程的知識,這種明顯的二分法並不讓我感到吃驚。有關詳細討論在不同情況下會發生什麼(特定於Microsoft,但似乎有助於作爲一般背景)here

總結:

要改變使用C++ 運行時庫的語言環境,使用locale類。 通過調用locale :: global方法, 更改每個線程 中的語言環境,該語言環境未明確啓用每個線程語言環境的 。要在應用程序的單個線程或部分 中更改 區域設置,只需在該 線程或代碼的一部分中創建一個區域設置對象的 實例。

1

聲明:我不是地區專家,所以這可能是錯誤的。

Multithreading and Locales Knowlegde Base文章就指出:

調用區域::全球變化 區域對於標準C++ 庫和C運行時庫。 但是,調用setlocale只有 會更改C Runtime 庫的語言環境;標準C++庫 不受影響。

您的確在使用C++ Std Lib,因此在我看來,您需要致電locale::global()。當我這樣做時,返回值如您所料。這裏是我的示例代碼:

#include <cstdlib> 
#include <locale> 
#include <sstream> 
using namespace std; 

int main() 
{ 

    //Enable per thread locale in current thread 
    int n = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) ; 

    //Create istringstream object 
    std::istringstream LibraryStream; 
    //Create double object 
    double Value = 0; 
    //Create std::locale object with "C" locale ("." as decimal point) 
    std::locale StreamLoc("C"); 
    //Set C Runtime locale to danish ("," as decimal point) 
    char* ret = setlocale(LC_ALL, "danish"); 

    //Set the "C" locale on the istringstream object 
    LibraryStream.imbue(StreamLoc); 
    locale::global(StreamLoc); 
    //Get the locale of the istringstream object for test (returns "C" as expected) 
    std::locale NewStreamLoc = LibraryStream.getloc(); 

    //Set floating point string with "C" locale decimal point in istringstream object 
    LibraryStream.str("60.258351"); 
    //Convert the string to double 
    LibraryStream >> Value; 

     //Now the expected value of "Value" is 60.258351, but it is 60.000 
    //when debugging the conversion, I can see that "," is used as decimal point 
} 
+0

是的,你調用locale :: global()會改變標準C++庫和C運行時庫的語言環境。 – TEB 2010-11-10 19:15:40

+0

但是我想保留C運行時庫的語言環境,並只使用imbue()方法在特定STL對象(istringstream LibraryStram)上使用語言環境。 – TEB 2010-11-10 19:18:40

+0

操作符>>值是否使用流中的語言環境或全局語言環境? – 2010-11-10 19:47:50

0

好點John Dibling。我已經測試過,操作符>> Value在流中使用語言環境,而不是全局語言環境。它是由下面的例子中進行了測試:

_configthreadlocale(_ENABLE_PER_THREAD_LOCALE),除去
區域設置::全球(區域( 「丹麥」));,加入到設置全局標準庫區域設置

#include <cstdlib> 
#include <locale> 
#include <sstream> 
using namespace std; 

int main() 
{ 
    //Enable per thread locale in current thread 
    //int n = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) ; 

    //Create istringstream object 
    std::istringstream LibraryStream; 
    //Create double object 
    double Value = 0; 
    //Create std::locale object with "C" locale ("." as decimal point) 
    std::locale StreamLoc("C"); 
    //Set C Runtime locale to danish ("," as decimal point) 
    char* ret = setlocale(LC_ALL, "danish"); 

    //Set Std lib global locale to "danish" 
    locale::global(locale("danish")); 

    //Set the "C" locale on the istringstream object 
    LibraryStream.imbue(StreamLoc); 

    //Get the locale of the istringstream object for test (returns "C" as expected) 
    std::locale NewStreamLoc = LibraryStream.getloc(); 

    //Set floating point string with "C" locale decimal point in istringstream object 
    LibraryStream.str("60.258351"); 
    //Convert the string to double 
    LibraryStream >> Value; 

    //In this case the value of "Value" is 60.258351, as expected and thus 
    //the "C" locale was use for conversion 
} 

我猜測迄今爲止的結論是,啓用了_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)的線程中的STL對象實際上正在使用C運行時區域設置。

有可能通過設置兩個標準庫的語言環境和C運行時的地區與區域::全球()調用來解決這個問題。但是由於Std lib語言環境不是線程安全的並且不受_ENABLE_PER_THREAD_LOCALE的影響,我們仍然可以使用此解決方法運行多線程問題。

相關問題