我的美国 Ini 文件可以使用欧洲格式的浮点数吗
Will my US Ini files work with European format floating points
我在 Windows 32 位 VCL 平台上使用 C++Builder XE4。
我正在设置 .INI
文件,其中包括使用句点 (.
) 作为小数点分隔符的浮点数。在欧洲,他们使用逗号 (,
) 作为小数点分隔符。
我正在使用 C++Builder 内置的 TIniFile
class。
TIniFile
会在欧洲阅读下面的文件条目吗?我需要第二个以逗号作为分隔符的 .INI
文件吗?
当我读取浮点值时,我的故障安全 return 值也使用句点 (.
)。在下面的代码中,
ReadFloat("Forex", "Size", 0.01 );
0.01 是故障安全 return 值。
这在欧洲行得通吗?
例如:
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 文件吗?
我只需要调整故障安全 return 值即可使用本地分隔符。
步骤 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 = '[=12=]'; //'[=12=]' 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;
}
}
在内部,ReadFloat()
使用 ReadString()
然后调用非 TFormatSettings
版本的 StrToFloat()
将 String
转换为 double
.同样,WriteFloat()
调用 FloatToStr()
的非 TFormatSettings
版本将 double
转换为 String
,然后调用 WriteString()
.
StrToFloat()
和 FloatToStr()
的那些版本取决于 SysUtils
单元中的全局 DecimalSeparator
变量,它是依赖于语言环境的。因此 NO,当 ReadFloat()
在使用与调用 WriteFloat()
.
的系统
要解决此问题,您有两种选择:
将全局 DecimalSeparator
变量的值更改为 '.'
。不推荐,但是可以做。
完全忘记 WriteFloat()
和 ReadFloat()
。直接使用 WriteString()
和 ReadString()
,自行处理浮点数转换,这样您就可以使用在所有系统上都一致的任何固定格式。
//Write TIniFile
TFormatSettings fmt = TFormatSettings::Create(); // get defaults
fmt.DecimalSeparator = _D('.');
fmt.ThousandSeparator = _D(','); // or '[=10=]' 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 '[=11=]' 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('[=12=]');
EuroFmt = TFormatSettings::Create();
EuroFmt.DecimalSeparator = _D(',');
EuroFmt.ThousandSeparator = _D('[=12=]');
}
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;
}
我在 Windows 32 位 VCL 平台上使用 C++Builder XE4。
我正在设置 .INI
文件,其中包括使用句点 (.
) 作为小数点分隔符的浮点数。在欧洲,他们使用逗号 (,
) 作为小数点分隔符。
我正在使用 C++Builder 内置的 TIniFile
class。
TIniFile
会在欧洲阅读下面的文件条目吗?我需要第二个以逗号作为分隔符的 .INI
文件吗?
当我读取浮点值时,我的故障安全 return 值也使用句点 (.
)。在下面的代码中,
ReadFloat("Forex", "Size", 0.01 );
0.01 是故障安全 return 值。
这在欧洲行得通吗?
例如:
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 文件吗?
我只需要调整故障安全 return 值即可使用本地分隔符。
步骤 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 = '[=12=]'; //'[=12=]' 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;
}
}
在内部,ReadFloat()
使用 ReadString()
然后调用非 TFormatSettings
版本的 StrToFloat()
将 String
转换为 double
.同样,WriteFloat()
调用 FloatToStr()
的非 TFormatSettings
版本将 double
转换为 String
,然后调用 WriteString()
.
StrToFloat()
和 FloatToStr()
的那些版本取决于 SysUtils
单元中的全局 DecimalSeparator
变量,它是依赖于语言环境的。因此 NO,当 ReadFloat()
在使用与调用 WriteFloat()
.
要解决此问题,您有两种选择:
将全局
DecimalSeparator
变量的值更改为'.'
。不推荐,但是可以做。完全忘记
WriteFloat()
和ReadFloat()
。直接使用WriteString()
和ReadString()
,自行处理浮点数转换,这样您就可以使用在所有系统上都一致的任何固定格式。//Write TIniFile TFormatSettings fmt = TFormatSettings::Create(); // get defaults fmt.DecimalSeparator = _D('.'); fmt.ThousandSeparator = _D(','); // or '[=10=]' 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 '[=11=]' 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('[=12=]');
EuroFmt = TFormatSettings::Create();
EuroFmt.DecimalSeparator = _D(',');
EuroFmt.ThousandSeparator = _D('[=12=]');
}
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;
}