1

Читаю значение атрибута с плавающей точкой с узла в файле XML с TXMLDocument:Как правильно прочитать значение с плавающей точкой из файла XML независимо от региональных настроек?

<MyApp_Favorites version="1.0"> 

... с этим утверждением:

var 
    ThisRootNode: IXMLNode; 
    ThisVersion: Single; 

// ... 

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

Однако на моей системе немецкого языка я получаю это значение версии:

ThisVersion = 10,00

... как в моих региональных настройках запятая "," определяется как десятичный разделитель, а не точка "." как в файле XML. Но с региональной настройкой на английском языке - где точка, скорее всего, определяется как установка десятичного разделителя - результат будет правильным, как «1.0».

Итак, как я могу убедиться, что независимо от региональной настройки чтение VALUE 1.0 будет всегда одинаковым? (Чтение значения версии как строки, а затем преобразование ее в float, похоже, не очень элегантный метод).

+0

Здесь мы снова злонамеренного downvoting моих законных и хорошо сформулированные вопросы по некоторым конкретным людям без каких-либо объяснений! – user1580348

ответ

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. 
+0

Спасибо @J ..., но это только версия формата файла XML и, следовательно, не так сложна. – user1580348

+0

@ user1580348 Я не уверен, что я назвал бы это «сложным» ... –

+0

Не в смысле сложного. Но ваше решение очень элегантно и полно. Спасибо! – user1580348

2

Это значение не должно рассматриваться как значение с плавающей запятой. Вы открываете себе проблемы с представлением двоичных типов с плавающей запятой. Гораздо лучше прочитать строку и проанализировать основные и второстепенные части, преобразуя их в целое число с StrToInt. Разделите строку непосредственно с помощью Pos, чтобы найти местоположение разделителя периодов или использовать любую функцию Split.

С другой стороны, даже не ясно, что вам нужно это значение в любом формате, отличном от строки. Так зачем же вообще что-то делать, кроме чтения строки?

Что касается актуального вопроса, который вы задали, если вы когда-нибудь захотите это сделать, используйте перегрузку StrToFloat, которая принимает параметр TFormatSettings. И перейдите в настройки формата, которые устанавливают десятичный разделитель как '.'.

+0

Ну, может быть, мне понадобится в будущем сделать арифметическое сравнение двух или более значений версии. – user1580348

+0

Не рассматривайте это как реальное значение. Это не. Это две целые числа, основная и второстепенная. –

+0

@ user1580348 Вы можете сделать это с помощью записи с помощью [Перегрузка оператора] (http://docwiki.embarcadero.com/RADStudio/Berlin/en/Operator_Overloading_ (Delphi) #Declaring_Operator_Overloads) –

5

Используйте строковое представление и сделать преобразование самостоятельно, используя TFormatSettings.Invariant:

ThisVersion := StrToFloat(ThisRootNode.Attributes['version'], TFormatSettings.Invariant); 
Смежные вопросы