AnsiString для двойного C++
Я пытаюсь преобразовать AnsiString
к double
, но после запуска программы он говорит: "20.60 не является допустимой плавающей точкой".
AnsiString Temperatur
RE_Temperatur->Text = Temperatur;
Chart1->Series[0]->AddXY(DT_Uhrzeit->Time, RE_Temperatur->Text.ToDouble(),
"", clRed);
Значение для Temperatur
приходит из соединения SerialPort с моего Arduino и доставляет что-то вроде 20.60 и так далее. Когда я обрезаю строку до первых двух цифр, она работает нормально. Угадай .
как-то связано с ошибкой, но я не знаю, как ее решить.
РЕДАКТИРОВАТЬ // Я сейчас попытался просто заменить "." с "," со следующим кодом:
RE_Temperatur->Text = StringReplace(RE_Temperatur->Text, ".", ",",
TReplaceFlags() << rfReplaceAll);
Теперь я получаю сообщение об ошибке "20,60 не является допустимой плавающей точкой". Это так расстраивает:/
3 ответа
Попробуйте этот простой кусок кода в новой консольной программе:
AnsiString Temperatur = "12.45"; // locale independent
AnsiString Temperatur2 = "12,45"; // correct in my German locale
double temp = StrToFloat(Temperatur, TFormatSettings::Invariant());
double temp2 = StrToFloat(Temperatur2); // In my case: German locale!
printf("%8.4f %8.4f\n", temp, temp2);
Выход:
12.4500 12.4500
Вы можете видеть, что это работает как ожидалось. Обратите внимание, что в моей системе запятая является десятичным разделителем для локали, и, тем не менее, этот код прекрасно работает с точкой в качестве десятичного разделителя из-за настроек инвариантного формата.
Так что делайте свой выбор: используйте TFormatSettings::Invariant()
если вам нужна независимость от локали, но не используйте ее, если вы хотите использовать десятичный разделитель для локали пользователя.
Вы можете использовать StrToFloat, у него есть вторая версия, которая принимает TFormatSettings
объект, который вы можете использовать для указания конкретного DecimalSeperator
, Кстати, он не возвращает float, так как его имя может означать, что он возвращает Extended
ака long double
,
Держу пари, что ваша проблема - десятичная точка. Используемый для него символ является одной из переменных среды Windows и может варьироваться от компьютера к компьютеру. Есть звонки winapi, чтобы получить его, но я не помню их...
Проблема с AnsiString("1.23").ToDouble()
в том, что catch/try
не поймает исключение (по крайней мере на моем компиляторе BDS2006). Есть обходные пути. я использую atoi()
вместо этого это не сбой, а скорее усечение до целого числа, когда присутствует недопустимый символ, поэтому его можно использовать для определения правильного знака десятичной точки и преобразования:
char _floating_point_char=' '; // decimal point separator
AnsiString strnum (AnsiString s,int sig=1,int pnt=1,int hex=0,char dot=_floating_point_char);
double str2num(AnsiString s,int sig=1,int pnt=1,int hex=0,char dot=_floating_point_char);
AnsiString strnum(AnsiString s,int sig,int pnt,int hex,char dot)
{
if (dot==' ')
{
float x;
x=atof("0.5"); if (x>=0.25) _floating_point_char='.';
x=atof("0,5"); if (x>=0.25) _floating_point_char=',';
dot=_floating_point_char;
}
int i,l,a,e,e0,exp=pnt;
AnsiString q="";
l=s.Length();
if (hex) exp=0; // exponent is e,E so it colide with hex e,E
e0=0; for (i=1;i<=l;i++)
{
e=0;
a=s[i];
if ((a>='0')&&(a<='9')) { e=1; q+=char(a ); sig=0; }
if ((a>='A')&&(a<='F'&&(hex))){ e=1; q+=char(a ); sig=0; }
if ((a>='a')&&(a<='f'&&(hex))){ e=1; q+=char(a ); sig=0; }
if ((a=='e')||(a=='E'))
if (!hex) { if (!exp) break; e=1; q+=char('e'); exp=0; sig=1; pnt=0; e0=0; }
if (a=='+') { if (!sig) break; e=1; sig=0; }
if (a=='-') { if (!sig) break; e=1; q+=char(a ); sig=0; }
if (a=='.') { if (!pnt) break; e=1; q+=char(dot); pnt=0; }
if (a==',') { if (!pnt) break; e=1; q+=char(dot); pnt=0; }
if ((e0)&&(!e)) break;
e0|=e;
}
if (q.Length()<=0) q="0";
return q;
}
double str2num(AnsiString s,int sig,int pnt,int hex,char dot)
{
return atof(strnum(s,sig,pnt,hex,dot).c_str());
}
Это просто обнаружить, если .
или же ,
является правильным, а затем заменить его в строке перед преобразованием... Грубая выборка правильного символа десятичной точки из winapi безопаснее, поскольку разделитель десятичной запятой может быть любым... Вы можете игнорировать hex
Часть я использую это для любых видов чисел...