当有人将包含字符串值的Variant分配给浮点变量时,Delphi会调用VarToDoubleAsString进行转换,而该转换又将OS设置用于十进制和千位分隔符(通过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.
第一个测试工作正常,第二个测试失败。
有没有一种方法可以使variant转换使用
SysUtils.DecimalSeparator
和SysUtils.ThousandSeparator
? 最佳答案
您可以根据自己的喜好替换VarR8FromStr
中的varutils.pas
函数,并且VarToDoubleAsString
将代替它使用:
function MyConversion(const strIn: WideString; LCID: Integer; dwFlags: Longint;
out dblOut: Double): HRESULT; stdcall;
const
CResult: array [False..True] of HRESULT = (VAR_INVALIDARG, VAR_OK);
var
s: string;
begin
s := StringReplace(StrIn, ThousandSeparator, '', [rfReplaceAll]);
Result := CResult[TryStrToFloat(s, dblOut)];
end;
[...]
begin
varutils.VarR8FromStr := MyConversion;
[...]
关于delphi - 使VarToDoubleAsString使用Delphi设置(而不是OS设置),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5090107/