是否可以使用DecimalSeparator强制Floattostr / Strtofloat函数使用小数点

时间:2012-03-21 22:57:23

标签: delphi

目前,我将DecimalSeparator设置为'。'在每个使用这些功能的程序中。

在程序开始时全局设置它会容易得多,但我发现Delphi似乎会定期将其设置回当前的语言环境。

我需要确保所有转换都使用小数点,无论程序使用哪个国家/地区,因为这是此类程序的标准,所有文件结构和通信协议,表单/编辑中的数字显示等等需要以这种方式格式化。

我在另一个帖子中被告知使用decimalseparator不是正确的方法,但我没有给出任何替代方案。我读过的关于这个主题的其他主题似乎没有提供任何形成性指导或过于复杂。

有一种简单的“正确”方法吗?

5 个答案:

答案 0 :(得分:20)

是的,运行期间RTL可能会更改DecimalSeparator全局变量,这在我意识到这一点之前几年前给我带来了很多麻烦。

事情是,当Windows小数分隔符更改时,RTL会更新DecimalSeparator,例如,使用“控制面板”。这似乎是一个相当小的问题。实际上,最终用户多久更改一次系统的小数点分隔符?

最大的问题是,每次切换用户(在Windows中)时,DecimalSeparator变量都会更新(根据系统设置)。这对我来说是一个惊喜。也就是说,如果您的系统设置使用逗号(',')作为小数点分隔符,并且在应用程序启动时设置DecimalSeparator := '.',那么如果切换用户,则DecimalSeparator将恢复为逗号(当你换回时你会注意到。)

您可以告诉RTL不要通过

更新小数分隔符
Application.UpdateFormatSettings := false;

无论如何,DecimalSeparator都有更好的替代方案,正如其他答案和评论中所讨论的那样。

答案 1 :(得分:13)

我/假设RTL不会触及全局DecimalSeperator变量。如果没有,那么所有这些例程都有一个可以使用的可选参数FormatSettings。 Globaly声明一个TFormatSettings变量,并将其用于这些例程的每次出现。

当您指定自己的格式设置时,它的一个小好处可能是例程是线程安全的。

答案 2 :(得分:7)

为了安全起见,我会使用TFormatSettings,这有两个好处:

  1. 格式化是线程安全的,其他代码/库不会影响您的功能。
  2. 您不会影响其他可能依赖某些设置的代码。
  3. 这是一种可能的实施方式:

    function FloatToStrWithDecimalPoint(const Value: Extended; const Format: String = '0.###'): String;
    var
      myFormatSettings: TFormatSettings;
    begin
      GetLocaleFormatSettings(GetThreadLocale, myFormatSettings);
      myFormatSettings.DecimalSeparator := '.';
      Result := FormatFloat(Format, Value, myFormatSettings);
    end;
    

答案 3 :(得分:2)

您可以在使用 ForceLocalSeparator() ForceDotSeparator()函数调用RTL函数之前和之后修补每个字符串。

// before a RTL call
Function ForceLocalSeparator(Const StrValue: String): String;
Var
  SepPos: Integer;
Begin
  Result := StrValue;
  If DecimalSeparator <> '.' Then
    Begin
      SepPos := Pos( '.', Result );
      If SepPos > 0 Then Result[SepPos] := DecimalSeparator;
    End;
End;

// after a RTL call
Function ForceDotSeparator(Const StrValue: String): String;
Var
  SepPos: Integer;
Begin
  Result := StrValue;
  If DecimalSeparator <> '.' Then
    Begin
      SepPos := Pos( DecimalSeparator, Result );
      If SepPos > 0 Then Result[SepPos] := '.';
    End;
End;

答案 4 :(得分:1)

没有其他选择,没关系。如果您的Delphi版本足够新,那么首选接受TFormatSettings参数的那些函数的版本,这样您就不会干扰依赖于该全局变量的任何其他代码来识别区域设置行为。

FloatToStrStrToFloat是区域设置敏感的函数。如果您需要将浮点值转换为字符串以将其保留在程序稍后将读取的某个位置(例如文件,注册表或网络套接字),那么您应该使用区域设置独立代替您的转化功能StrVal 。无论.变量或其他环境设置如何,它们始终使用DecimalSeparator作为小数点分隔符。