1

我正在从 XML 文件中的节点读取浮点属性值TXMLDocument

<MyApp_Favorites version="1.0">

...有了这个声明:

var
  ThisRootNode: IXMLNode;
  ThisVersion: Single;

// ...

ThisVersion := ThisRootNode.Attributes['version'];
CodeSite.Send('ThisVersion', ThisVersion);

但是,在我的德语系统上,我得到了这个版本值:

这个版本 = 10,00

...在我的区域设置中,逗号“,”被定义为小数分隔符,而不是点“。” 就像在 XML 文件中一样。但是使用英语区域设置 - 其中点最有可能定义为小数分隔符设置 - 结果将正确为“1.0”。

那么如何确保独立于区域设置的1.0读取值始终相同?(将版本值读取为字符串,然后将其转换为浮点数似乎不是一个非常优雅的方法)。

4

3 回答 3

5

使用字符串表示并使用以下方法自己进行转换TFormatSettings.Invariant

ThisVersion := StrToFloat(ThisRootNode.Attributes['version'], TFormatSettings.Invariant);
于 2016-12-19T15:20:50.703 回答
3

浮点数不是版本号的明智格式,舍入错误和缺乏可表示性是主要缺点。考虑使用带有整数的记录来定义版本号。

program Project1;
{$APPTYPE CONSOLE}

uses
  SysUtils, StrUtils, Types;
type    
TVersion = record
  private
    procedure Set_AsString(AVersion : string);
    function Get_AsString: String;
  public
    Major: Integer;
    Minor: Integer;
    property AsString: String read Get_AsString write Set_AsString;
end;    

function TVersion.Get_AsString: String;
begin
  Result := Format('%d.%d', [Major, Minor]);
end;

procedure TVersion.Set_AsString(AVersion: string);
var
  split : TStringDynArray;
begin
  split := SplitString(AVersion, '.');
  Major := StrToInt(split[0]);
  Minor := StrToInt(split[1]);
end;

var
  v1, v2 : TVersion;
  s : string;
begin
  v1.Major := 12;
  v1.Minor := 34;
  WriteLn(v1.AsString);

  s := v1.AsString;
  v2.AsString := s;

  WriteLn(v2.AsString);
  ReadLn;
end.
于 2016-12-19T14:31:12.560 回答
2

该值不应被视为浮点值。您对二进制浮点类型的表示问题敞开心扉。更好的是读取字符串并解析出主要和次要部分,将它们转换为整数StrToInt。使用拆分字符串本身Pos来查找句点分隔符的位置,或者实际上使用任何Split函数。

另一方面,甚至不清楚您是否需要字符串以外的任何格式的此值。那么,除了将其作为字符串读取之外,为什么还要费心去做任何事情呢?

至于您提出的实际问题,您是否希望使用StrToFloat接受TFormatSettings参数的重载来做到这一点。并传入将小数点分隔符设置为的格式设置'.'

于 2016-12-19T14:41:18.727 回答