2017-03-10 94 views
2

我正在使用Windows 32位VCL平臺的C++ Builder XE4。我的美國Ini文件將使用歐洲格式的浮點數嗎

我正在設置.INI文件,其中包括使用小數點分隔符的句點(.)的浮點數。在歐洲,他們使用逗號(,)作爲小數分隔符。

我正在使用內置於C++ Builder的TIniFile類。

TIniFile閱讀下面的文件在歐洲?我需要第二個.INI文件,逗號作爲分隔符嗎?

當我讀取浮點值時,我的故障安全返回值還使用句點(.)。在下面的代碼中,

ReadFloat("Forex", "Size", 0.01 ); 

0.01是故障安全返回值。

這會在歐洲工作嗎?

例如:

MyList.ini:

[Forex] 
Size=0.0001 
Value=10.5 
OffSet=0.01 


//Read TIniFile 
MyList = new TIniFile("C:\\MyList.ini"); 
double r_Size = MyList->ReadFloat("Forex", "Size", 0.01); 
double r_Value = MyList->ReadFloat("Forex", "Value", 10.0); 
double r_OffSet = MyList->ReadFloat("Forex", "OffSet", 0.01); 

編輯低於

你在你的答案表明,如果TIniFile寫和會正確地讀出相同的位置讀取。是否可以打開並重新保存我的.INI文件一次以將它們轉換爲本地格式?然後,我可以使用我當前的代碼而不改變。我將在循環中爲我的.INI文件中的每個浮點執行以下三個步驟。這將工作重新格式化.INI文件?

我只需要調整故障安全返回值以使用本地分隔符。

步驟1)檢查分離
步驟2)負載浮動的本地價值使用美國格式(。)分隔
步驟與當地分離器3)重新保存

void __fastcall ConvertToLocalSeparator(){ 

//1 Check Local Value of Seperator 
TFormatSettings fmt = TFormatSettings::Create(); 
UnicodeString Local = fmt.DecimalSeparator; 
UnicodeString Euro = ","; 

if(CompareText(Local, Euro)==0){ //Local DecimalSeparator is Coma(,) 

//2 Load Float using US format (.) Separator 
TFormatSettings USfmt = TFormatSettings::Create(); // get defaults 
USfmt.DecimalSeparator = '.'; 
USfmt.ThousandSeparator = '\0'; //'\0' to disable 

TIniFile *MyList; 
MyList = new TIniFile("C:\\MyList.ini"); 
double r_Size = StrToFloatDef(MyList->ReadString("Forex", "Size", ""), 0.01, USfmt); 
delete MyList; 
MyList=NULL; 

//3 Re-Save with local Separator 
MyList = new TIniFile("C:\\MyList.ini"); 
MyList->WriteFloat("Forex", "Size", r_Size ); 
delete MyList; 
MyList=NULL; 
} 

} 

回答

7

內部,ReadFloat()使用ReadString()和然後調用NON- TFormatSettings版本StrToFloat()String轉換爲double。同樣,WriteFloat()調用NON- TFormatSettings版本FloatToStr()double轉換爲String,然後調用WriteString()

StrToFloat()FloatToStr()那些版本取決於在SysUtils單元,其是區域設置相關的全局DecimalSeparator變量。所以,您現有的代碼將原樣工作時ReadFloat()在系統上使用不同的區域設置比調用WriteFloat()系統。

要解決這個問題,你有兩個選擇:

  1. 變化的全球DecimalSeparator變量來'.'值。不推薦,但可以完成。

  2. 忘記WriteFloat()ReadFloat()。直接使用WriteString()ReadString(),自己處理浮動轉換,以便您可以使用任何固定的格式,您希望在所有系統上保持一致。

    //Write TIniFile 
    
    TFormatSettings fmt = TFormatSettings::Create(); // get defaults 
    fmt.DecimalSeparator = _D('.'); 
    fmt.ThousandSeparator = _D(','); // or '\0' to disable 
    
    MyList = new TIniFile(_D("C:\\MyList.ini")); 
    MyList->WriteString(_D("Forex"), _D("Size"), FloatToStr(r_Size, fmt)); 
    MyList->WriteString(_D("Forex"), _D("Value"), FloatToStr(r_Value, fmt)); 
    MyList->WriteString(_D("Forex"), _D("OffSet"), FloatToStr(r_OffSet, fmt)); 
    

    //Read TIniFile 
    
    TFormatSettings fmt = TFormatSettings::Create(); 
    fmt.DecimalSeparator = _D('.'); 
    fmt.ThousandSeparator = _D(','); // or '\0' to disable 
    
    MyList = new TIniFile(_D("C:\\MyList.ini")); 
    double r_Size = StrToFloatDef(MyList->ReadString(_D("Forex"), _D("Size"), _D("")), 0.01, fmt); 
    double r_Value = StrToFloatDef(MyList->ReadString(_D("Forex"), _D("Value"), _D("")), 10.0, fmt); 
    double r_OffSet = StrToFloatDef(MyList->ReadString(_D("Forex"), _D("OffSet"), _D("")), 0.01, fmt); 
    

更新:如果你想閱讀和使用本地格式(我不推薦)重新保存文件,你可以嘗試更類似的東西:

TFormatSettings USFmt; 
TFormatSettings EuroFmt; 

void __fastcall InitFormats() 
{ 
    USFmt = TFormatSettings::Create(); 
    USFmt.DecimalSeparator = _D('.'); 
    USFmt.ThousandSeparator = _D('\0'); 

    EuroFmt = TFormatSettings::Create(); 
    EuroFmt.DecimalSeparator = _D(','); 
    EuroFmt.ThousandSeparator = _D('\0'); 
} 

void __fastcall CheckLocalFormat(TCustomIniFile *Ini, String Section, String Name, double Default) 
{ 
    double value; 
    String s = Ini->ReadString(Section, Name, _D("")); 
    if (!TryStrToFloat(s, value)) 
    { 
     if (!TryStrToFloat(s, value, USFmt) && !TryStrToFloat(s, value, EuroFmt)) 
      value = Default; 
     Ini->WriteFloat(Section, Name, value); 
    } 
} 

void __fastcall CheckLocalFormat() 
{ 
    TIniFile *MyList = new TIniFile(_D("C:\\MyList.ini")); 
    CheckLocalFormat(MyList, _D("Forex"), _D("Size"), 0.01); 
    CheckLocalFormat(MyList, _D("Forex"), _D("Value"), 10.0); 
    CheckLocalFormat(MyList, _D("Forex"), _D("Offset"), 0.01); 
    delete MyList; 
} 
+0

當然,使用'TFormatSettings :: Invariant'編寫和閱讀也可以。它在任何地方都是一樣的(或多或少與美國格式設置AFAIK相同)。然後,不需要設置小數點和千位分隔符。我不確定這是否已經在XE4中可用,但我會這麼認爲。否則,可以使用TFormatSettings構造函數來獲取它。 –

+0

我在TMemIniFile和TIniFile上測試了這個解決方案,它似乎可以和兩者一起正常工作。謝謝 – homebase

+0

Remy,你能解釋你爲什麼在你的例子中使用_D嗎?我在Embarcadero的wiki上發現了有限的關於TStringBuilder的文檔,並且不太瞭解它在做什麼。 _D似乎只用於引號「」中的文本。 – homebase

相關問題