Помощь с превращением массива символов в float

Sklyanskiy
Offline
Зарегистрирован: 25.03.2019

Вообщем, имею массив типа char. Для примера возьмем такой: "546.876". Задача превратить его в переменную типа float с учётом этой точки. Числа могут быть рандомные и точка может стоять в любой часте либо её может не быть вовсе. Подскажите пожалуйста как реализовать подобное. Я написал вот такой код:

float num1//результат должен быть здесь
int indexNum = x;//величина массива
char charedNum[];//сам массив

for(int i = 0; i < indexNum; i++){//запускаем цыкл, не нарушая границ массива
    if(charedNum[i] != '.'){//проверка на точку
      num1 = num1*10+cToI(charedNum[i]);//если это действительно цифры, то без лишних заморочек складываем в число
    }else{//если всё же попалась точка
      if( (i+1)<indexNum ){//проверяем есть ли еще цыфра после точки(защита от дурака, чтобы небыло такого: 5467.)
        num1 = (num1*10+cToI(charedNum[i+1])) / 10;//прибавляем следующий знак после точки и сразу ставим эту точку перед ним
        i++;
      }
    }
 }

Но этот код имеет сладующую проблему:

Если число без точки, то работает отлично.

Если в числе точка перед последним знаком(например 23456677,1), то работает отлично

Если в числе точка не перед последним знаком(например 23,545), то она исчезает, через постоянное умножение на 10. Буду благодарен за помощь и подробное объяснение.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А что там объснять. Существуют два режима - до точки и после точки . До точки - умножить на 10 и прибавить цифру. После точки - вес разряда разделить на 10 , умножить на цифру и прибавить к результату. В общем обычный автомат. 

Sklyanskiy
Offline
Зарегистрирован: 25.03.2019

qwone пишет:

А что там объснять. Существуют два режима - до точки и после точки . До точки - умножить на 10 и прибавить цифру. После точки - вес разряда разделить на 10 , умножить на цифру и прибавить к результату. В общем обычный автомат. 


Не очень понял. "вес разряда" это что? Никогда раньше не стыкался с данным термином. Можете привести пример работы во втором режиме?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

зачем велик изобретать? 

https://www.microchip.com/webdoc/AVRLibcReferenceManual/group__avr__stdlib_1ga5ee4d110a3bb55d2eadda05e3ebedf8a.html

использование 

float f = strtod("123.456",NULL);

иле 

char *numptr = "123.456";

float f = strtod(numptr, NULL);

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ты б чонить почитал за RTL AVR GCC, там и не такое есть

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Деда слушайте он дело говорит.

Если число всегда до конца строки, то можно ещё проще

float a = atof("3.141592");

А теперь гуглим strtod и atof

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ЕвгенийП пишет:

Если число всегда до конца строки, то можно ещё проще

float a = atof("3.141592");

А она разве не до первого неконвертируемого символа? 

а то я так время разбираю 

uint8_t hour = atoi(__TIME__[0]);  TIME  в виде 'HH:MM:SS'

uint8_t min = atoi(__TIME__[3]); - первый символ после ":'

uint8_t sec = atoi(__TIME__[6]); - аналагична

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, да, а с этим проблемы у ТС? Ой, понял, ну я это и имел в виду, считая \0 таким символом. strtod - ей же можно конец указать явно.

Да, кстати, дед, если не передамли, давайте на ты перейдём.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ЕвгенийП пишет:

Да, кстати, дед, если не передамли, давайте на ты перейдём.

Я буду тока рад. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ок!

mixail844
Offline
Зарегистрирован: 30.04.2012

DetSimen пишет:

ЕвгенийП пишет:

Если число всегда до конца строки, то можно ещё проще

float a = atof("3.141592");

А она разве не до первого неконвертируемого символа? 

а то я так время разбираю 

uint8_t hour = atoi(__TIME__[0]);  TIME  в виде 'HH:MM:SS'

uint8_t min = atoi(__TIME__[3]); - первый символ после ":'

uint8_t sec = atoi(__TIME__[6]); - аналагична

часы еще можно вот так разбирать : 

int main()
{
    char tmp_time[] = "22:15:19"; 
    int hrs,min,sec;
    sscanf(tmp_time,"%d:%d:%d",&hrs,&min,&sec);
    printf("hrs %d min %d sec %d" ,hrs,min,sec);

    return 0;
}

 

Sklyanskiy
Offline
Зарегистрирован: 25.03.2019

Мда... А если число не всегда до конца строки? Может быть к примеру просто 3 или 4.56. Тогда функция atof будет нормально работать?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

mixail844 пишет:

часы еще можно вот так разбирать : 

    sscanf(tmp_time,"%d:%d:%d",&hrs,&min,&sec);

можно.  Но sscanf он, сука, тяжелый. :) 

Sklyanskiy
Offline
Зарегистрирован: 25.03.2019

Пожалуйста помогите с первоначальной задачей. У меня массив может быть забит чем угодно, но переводить нужно только то кол-во знаков, которое казано у переменной indexNum

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Sklyanskiy пишет:

Пожалуйста помогите с первоначальной задачей. У меня массив может быть забит чем угодно, но переводить нужно только то кол-во знаков, которое казано у переменной indexNum

птваюмать. я тебе ссылку для чего дал?   ТАМ ВСЁ НАПИСАНО.

Пацказываю,  читай за ВТОРОЙ параметр strtod()

Sklyanskiy
Offline
Зарегистрирован: 25.03.2019

DetSimen пишет:

Sklyanskiy пишет:

Пожалуйста помогите с первоначальной задачей. У меня массив может быть забит чем угодно, но переводить нужно только то кол-во знаков, которое казано у переменной indexNum

птваюмать. я тебе ссылку для чего дал?   ТАМ ВСЁ НАПИСАНО.

Пацказываю,  читай за ВТОРОЙ параметр strtod()


Ответьте пожалуйста "да" или "нет". Второй параметр strtod() это ссылка на елемент массива на котором преобразование должно остановиться?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

наконец то.  ДА!

Sklyanskiy
Offline
Зарегистрирован: 25.03.2019

DetSimen пишет:

наконец то.  ДА!


Спасибо Вам огромное. Извините уже дурака, за поттупливание. Только начинаю учиться. Ещё раз спасибо.

Sklyanskiy
Offline
Зарегистрирован: 25.03.2019

DetSimen пишет:

наконец то.  ДА!

Я наверно снова что-то не понял. В чем проблема этого кода?

char *indexAdress;//создаю указатель
indexAdress = &charedNum[indexNum];//указатель на элемент массива
num1 = strtod(charedNum, indexAdress);//передаю функции массив и указатель

Выдает следующую ошибку:

Arduino: 1.8.8 (Windows 10), Плата:"WAVGAT UNO R3"

Внимание: platform.txt из ядра 'Arduino AVR Boards' содержит устаревшие recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}", автоматически преобразовано в recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}". Ожидайте обновления ядра.
C:\Users\Sklyanskiy\Documents\ArduinoProjects\notSimpleCalculator-v1.0\notSimpleCalculator-v1.0.ino: In function 'void transferMassInNum1()':

notSimpleCalculator-v1.0:113:39: error: cannot convert 'char*' to 'char**' for argument '2' to 'double strtod(const char*, char**)'

   num1 = strtod(charedNum, indexAdress);

                                       ^

exit status 1
cannot convert 'char*' to 'char**' for argument '2' to 'double strtod(const char*, char**)'

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Компилятор хочет не указатель, а массив указателей. Если это о чём-то говорит, конечно.

Sklyanskiy
Offline
Зарегистрирован: 25.03.2019

sadman41 пишет:

Компилятор хочет не указатель, а массив указателей. Если это о чём-то говорит, конечно.

Понял, спасибо.