Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > StrToFloat - преобразовать запятую в точку


Автор: Чoо 6.3.2010, 15:28
вобщем вопрос в следующем: взависимосты от языковых настроек системы функция StrToFloat в строковой переменной использует для разделения целой части от дробной символ точки или символ запятой. Если, скажем, языковые настройки Русский, то функция будет ругаться на точку, а если яз. настройки Английский, то на запятую. Так вот, как сделать так, что бы взависимости от языковых настроек точка преобразовывалась в запятую и наоборот?
Я прост даже не знаю как получить язык системы, так бы может попытался решить вопрос. Справку делфи читал, но что-то не нашел то что нужно. 

Автор: Coder 6.3.2010, 15:46
Код

{ Формирование и возврат FormatSettings с установленной десятичной точкой }
function DotSettings: TFormatSettings;
begin
  GetLocaleFormatSettings (GetThreadLocale, Result);
  Result.DecimalSeparator := '.';
end;

{ Формирование и возврат FormatSettings с установленной десятичной запятой }
function CommaSettings: TFormatSettings;
begin
  GetLocaleFormatSettings (GetThreadLocale, Result);
  Result.DecimalSeparator := ',';
end;

{ StrToFloat с точкой в роли десятичного разделителя }
function StrToFloatDot(const Value: string): c_float;
begin
  Result := StrToFloat (Value, DotSettings);
end;

{ StrToFloat с запятой в роли десятичного разделителя }
function StrToFloatComma(const Value: string): c_float;
begin
  Result := StrToFloat (Value, CommaSettings);
end;

function StrToFloatAny (const Value: string): c_float;
begin
  if not TryStrToFloat (Value, Result, CommaSettings) then
    Result := StrToFloat (Value, DotSettings);
end;

{ TryStrToFloat с точкой в роли десятичного разделителя }
function TryStrToFloatDot (const Value: string; out FValue: c_float): boolean;
begin
  Result := TryStrToFloat (Value, FValue, DotSettings);
end;

{ TryStrToFloat с запятой в роли десятичного разделителя }
function TryStrToFloatComma (const Value: string; out FValue: c_float): boolean;
begin
  Result := TryStrToFloat (Value, FValue, CommaSettings);
end;

function TryStrToFloatAny(const Value: string; out FValue: c_float): boolean;
begin
  Result:=TryStrToFloatComma(Value, FValue);  // пробуем перевести используя запятую

  if not Result then                  // если не прошло пробуем точку
    Result:=TryStrToFloatDot(Value, FValue);
end;


c_float = single

Автор: Данкинг 6.3.2010, 16:44
В общем случае - задавай принудительно разделитель (DecimalSeparator := ',') при создании формы.

Автор: Чoо 6.3.2010, 17:24
Coder, Данкинг, Спасибо за помощь. 
Вопрос отмечаю решенным. 

Автор: Coder 7.3.2010, 14:57
Цитата(Данкинг @  7.3.2010,  00:44 Найти цитируемый пост)
В общем случае - задавай принудительно разделитель (DecimalSeparator := ',') при создании формы.


Автор никогда так не делай!!! На этом можно очень сильно обжечься. Был горький опыт :(

Автор: Чoо 9.3.2010, 03:13
Coder, хорошо, поверю горькому опыту smile

Автор: Coder 9.3.2010, 04:10
Цитата(Чoо @ 9.3.2010,  11:13)
Coder, хорошо, поверю горькому опыту smile

Грубо говоря, когда на 100 машинах софт работает отменно находится 2-3, где программа начинает гнать в самом неожиданном месте. Как оказалось, у клиента стоит софт, который меняет в системе параметр DecimalSeparator. А выяснялось это долго и нудно.
Самое интересно, что еще давно про DecimalSeparator я вычитал на форуме. Так что доверяй, проверяй и используй с умом.

Автор: pseud 9.3.2010, 10:23
Цитата(Чoо @  6.3.2010,  17:24 Найти цитируемый пост)
Coder, Данкинг, Спасибо за помощь. Вопрос отмечаю решенным. 

не торопись, я тоже выступлю.
перед форматированием заменяй все точки и все запятые на DecimalSeparator.
Код

var
  s: string;
  f: Extended;
begin
  s := MyValue;
  s := StringReplace(s,'.',DecimalSeparator,[]);
  s := StringReplace(s,',',DecimalSeparator,[]);
  f := StrToFloat(s);
end;

Цитата(Данкинг @  6.3.2010,  16:44 Найти цитируемый пост)
В общем случае - задавай принудительно разделитель (DecimalSeparator := ',') при создании формы.

очень не рекомендую

Автор: Чoо 9.3.2010, 15:33
pseud, ух, довольно гибкий вариант smile
кстати программу скомпилил по пути наименьшего сопротивления и принудительно задал разделитель smile, хорошо, что предупредили о возможных глюках smile. А вот у меня вопрос такой: вот когда мы задаем разделитель, мы его задаем в самой системе или только для приложения? интересна природа глюков. программа пока тестировалась только на русскоязычных ОС.

Автор: pseud 10.3.2010, 15:18
Цитата(Чoо @  9.3.2010,  15:33 Найти цитируемый пост)
вот когда мы задаем разделитель, мы его задаем в самой системе или только для приложения?

DecimalSeparator - это глобальная переменная приложения, которая инициализируется из системной пременной. 
Ты ее можешь переопределить. Но это не хорошо. Представь, если сторонние компоненты будут переопределять ее, как им захочется. Тебе будет больно и обидно. Лучше научись жить с ней универсально.

Автор: Чoо 10.3.2010, 18:25
pseud, ну и времени на отладку уйдет немеренно. Ок, понял, спасиб smile.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)