2016-02-03 201 views
2

我有一個Linux系統設置爲某些語言環境並運行C++應用程序。我可以從C++應用程序或操作系統本身執行std::setlocale(LC_NUMERIC, "en_US.UTF-8")(通過更改/etc/default/locale)。我沒有訪問主要功能,所以我在我的功能std::setlocale(LC_NUMERIC, "en_US.UTF-8"),它工作正常。在對象級別或應用程序級別使用setlocale

但是,我想在我的應用程序中做一個對象級別或某個全局級別(一次)。我在網上看了很多,但沒有找到太多的幫助,所以決定問。這裏是我的結構GPS定位

所以,基本上

//struct Position : std::numpunct<char> { 
    struct Position { 
    Position() { isValid = PR_FALSE; lat = 0; lng = 0; elevation = 0; }; 
    PRBool isValid; 
    double lat; 
    double lng; 
    double elevation; 
    //char do_decimal_point() const { return '.'; } // separate with slash 
}; 

,然後在我的功能我做

mycheckposition(){ 

Position checkPosition; 
Position mPosition; 
// get some data in above. 

double distance; 
GetDistanceBetweenWGS84Coords(checkPosition, mPosition, distance); 

} 

我的問題是在哪裏,應該怎麼辦有效和安全的setlocale。我的位置值獲取逗號而不是點,然後GetDistanceBetweenWGS84Coords失敗。我的系統上的LC_NUMERIC代表逗號爲帶小數的數字。可能是,如果有人想看到GetDistance函數,在這裏。

int GetDistanceBetweenWGS84Coords(const Position& from, const 
Position& to, double& distance) 
{ 
const double EARTH_RADIUS_IN_METERS = 6372797.560856; 
const double DEG_TO_RAD = 0.017453292519943295769236907684886; 

double latitudeArc = (from.lat - to.lat) * DEG_TO_RAD; 
double longitudeArc = (from.lng - to.lng) * DEG_TO_RAD; 
double latitudeH = sin(latitudeArc * 0.5); 
latitudeH *= latitudeH; 
double lontitudeH = sin(longitudeArc * 0.5); 
lontitudeH *= lontitudeH; 
double tmp = cos(from.lat*DEG_TO_RAD) * cos(to.lat*DEG_TO_RAD); 

double arcInRadians = 2.0 * asin(sqrt(latitudeH + tmp*lontitudeH)); 
distance = EARTH_RADIUS_IN_METERS * arcInRadians; 

return 0; //success 
} 

我確實發現了一些能夠解決我的問題,但還沒有設法實現這個工作。不知道this鏈接的描述是否遵循std lib。

+1

有什麼問題嗎?你正在寫一個插件,它多次調用'setlocale'?加載插件時應用程序沒有設置安裝鉤子嗎?如果沒有,只需使用'bool' global來避免再次調用它。但是,更改應用程序的區域設置對於插件來說可能不是那麼好的行爲,所以您可能想要考慮避免依賴區域設置,或使用本地化的API,比如'strtol_l'。 – Potatoswatter

+0

@Patatoswatter'''strtol_l'''看起來像是有用的東西。有什麼地方我可以看看嗎?或者是strtol。此外,我的插件有一個init函數,但我在那裏做了setlocale,但它沒有效果。對於我的情況,setlocale只有在我如上所述或者在OS上設置LC_NUMERIC時纔有效。 – sb32134

+1

我解決了以下問題:''''std :: istringstream istrLat(NS_ConvertUTF16toUTF8(value).get()); istrLat >> checkPosition.lat; ''我從[這裏]得到了提示(http://stackoverflow.com/questions/1333451/locale-independent-atof)。這裏最重要的是''std :: istringstream''',正如鏈接所說,推理是「*標準iostream默認使用全局語言環境(反過來應該初始化爲經典(US)語言環境)*「 – sb32134

回答

1

前段時間我給出了一個類似的問題的答案,並試圖澄清與區域設置的問題,所以如果你想知道更多:stod does not work correctly with boost::locale。簡而言之:

  1. 這不是一件很好的事打電話給std::setlocale在您的插件,因爲它是整個應用程序的全局狀態,你可以搞砸了應用程序的其他部分。至少你應該儘快重置語言環境。

  2. 如果使用std::streamstringstreamcincout),比流的locale在創建流對象的時刻的全球C++語言環境的值相匹配。通常它是經典的「C」語言環境。但是沒有保證,因爲應用程序的某些部分可以操縱這個,就像你一樣。

  3. 您可以通過調用std::stream::imbue來確保std::stream具有理想的語言環境。這隻會操縱你的流而不是全局狀態。

例如:

std::stringstream stream; 
stream.imbue(std::locale::classic());//classical locale "C" with separator '.' 
+0

我測試了你的例子,它工作正常。基本上與上面評論中的鏈接相同。但是你的觀點3是有效的,也就是說,它確保使用''stream :: imbue'''。 – sb32134

相關問題