当我们将一个包含字符串值的 Variant 分配给浮点变量时,Delphi 调用 VarToDoubleAsString 进行转换,VarToDoubleAsString 又通过 VarR8FromStr 使用操作系统设置的小数和千位分隔符进行转换。如果我们需要更改 SysUtils.DecimalSeparator 和 SysUtils.ThousandSeparator,则这会带来问题。例如运行以下程序:
program VarStrToFloat;
{$APPTYPE CONSOLE}
uses
SysUtils,
Math;
function FormatFloatUsingDelphiSettings(Value: Extended): string;
begin
Result := FormatFloat('#,##0.00', Value);
end;
procedure Test(const AMsg: string);
var
r1, r2: Extended;
s1, s2: string;
v: Variant;
begin
r1 := 5432.1;
s1 := FormatFloatUsingDelphiSettings(r1);
v := s1; // <== conversion uses OS settings
r2 := v;
s2 := FormatFloatUsingDelphiSettings(r2);
Write(AMsg: 8, s1: 10, s2: 10, ' ');
if SameValue(r1, r2) then
Writeln('OK')
else
Writeln('FAIL');
end;
procedure SwapEm;
var
tmp: Char;
begin
tmp := DecimalSeparator;
DecimalSeparator := ThousandSeparator;
ThousandSeparator := tmp;
end;
begin
Test('Default');
SwapEm;
Test('Changed');
Readln;
end.
第一个测试正常工作,第二个测试失败。
是否有一种方法可以使变量转换使用 SysUtils.DecimalSeparator
和 SysUtils.ThousandSeparator
?
SetVariantManager
)的方法,但是在最近的版本中已经被删除了。好吧,它还在那里,只是没有任何作用。出于某些复杂的原因(QC#87786),我需要替换_VarFromCurr
。您可以通过替换_VarToDouble
来实现所需的功能,但这可能会更加困难(涉及一些钩子)。当然,可能有一种官方的方法可以做到这一点,但我不知道..... - David Heffernan