Преобразование char [] в float или double - c ++ - PullRequest
0 голосов
/ 12 мая 2018

ОБНОВЛЕНИЕ согласно TNTFreaks инструкции ответа.

У меня определены данные переменной типа char, такие как:

#define CMD_LEN 4
char data[CMD_LEN + 1];
float n1;

# I pass the data variable to `serial_read` function
n = serial_read(serial_fd, data, CMD_LEN, TIMEOUT);

# Here, the process goes to  serial_read function more below and
# after it return here again to follow ...


std::cout << "Data brought from serial_read method " << data << std::endl;

flush = tcflush(serial_fd, TCIOFLUSH);
//n = n*0.01f;

cout << "Applying sscanf " << std::endl;
sscanf(data, "%f", &n1);
printf("%.3f" "%s", n1, "  ");
n1 = atof(data) * 0.5f;
printf("%.3f", n1);
cout << "n1 value which have data turn it " << n1 << std::endl;

Когда компилятор проверяет функцию serial_read, введите для этого процесса:

* Примечание: я набираю эту serial_read функцию только в целях иллюстрации относительно рабочего процесса, который следует моему вопросу в процессе относительно data переменной *

    int SerialDriver::serial_read(int serial_fd, char *data, int size, int timeout_usec)
{
    std::cout << "Enter to serial_read method " << std::endl;
    fd_set fds;
    struct timeval timeout;
    bool band = false;
    int count = 0;
    int ret;
    int n;

    //-- Wait for the data. A block of size bytes is expected to arrive
    //-- within the timeout_usec time. This block can be received as
    //-- smaller blocks.
    do
    {
        //-- Set the fds variable to wait for the serial descriptor
        FD_ZERO(&fds);
        FD_SET(serial_fd, &fds);

        //-- Set the timeout in usec.
        timeout.tv_sec = 0;
        timeout.tv_usec = timeout_usec;
        // std::cout << "timeouts establecidos " << std::endl;

        //-- Wait for the data
        ret = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
        //-- If there are data waiting: read it
        if (ret == 1)
        {
            //-- Read the data (n bytes)
            n = read(serial_fd, &data[count], 1);
            // read viene de sofa/src/applications/plugins/SofaPML/argumentParser.h
            std::cout << "Enter to read method to read hapkit data via serial port " << std::endl;

            if (band)
            {
                if (data[count] != ' ')
                {
                    if (data[count] == '\n')
                    {
                        data[count] = '\0';
                        return count;
                    }
                    //-- The number of bytes receives is increased in n
                    count += n;
                }
            }
            if (!band && data[count] == '\n')
            {
                band = true;
            }
            //-- The last byte is always a 0 (for printing the string data)
            data[count] = 0;
        }
        std::cout << "band value: " << band << " and data: " << data << std::endl;

        //-- Repeat the loop until a data block of size bytes is received or
        //-- a timeout occurs
    } while (count < size && ret == 1);

    //-- Return the number of bytes reads. 0 If a timeout has occurred.
    std::cout << "Leaving serial_read method " << std::endl;
    std::cout << "count value " << count << std::endl;
    return count;

}

Когда функция serial_read завершается, возвращается data и значение char, как в примере 1.86

Я хочу преобразовать его в плавающее, используя atof(), например, я набираю секцию кода в начале кода моего вопроса и сохраняю результат в переменной n1 но вывод, который я получаю:

Data brought from serial_read method 1.86
Applying sscanf 
1,000  0,500n1 value which have data turn it 0.5
Serial Driver draw n1: 0.5 1
1,000

Значение 1000 - это data значение, которое я получаю, равное 1,86, но при этом убираем десятичные части или не включаем данные с фиксированным значением.

В итоге возможно, что я не передаю хороший путь параметру в функцию atof, (моя переменная n1 - float). Что касается функции sscanf, то я передаю & n1 в sscanf как ссылочный параметр для данных, которые необходимо преобразовать с помощью atof, но это не работает

Я получаю тот же результат. Я думал, что это возможно, хотя я понимаю инструкции TNTFreaks . Я не правильно их применяю?

что я делаю не так?

1 Ответ

0 голосов
/ 12 мая 2018

Прежде всего, char - это тип переменной, который может содержать только один или массив символов, а не строку символов. Вы можете иметь в виду const char* data = "6.35", который является строкой в ​​стиле c и что функция atof() требует в качестве ввода. Я бы использовал data как const char*, если вы не следуете моей рекомендации ниже и по-прежнему хотите использовать sscanf() вместо cin.

В c ++ использовать строки проще, чем const char* или массивы символов. Я бы объявил данные в виде строки, получил бы ввод и затем преобразовал бы его в const char*, используя c_str(), чтобы atof() мог использовать его.

atof возвращает double, а не число с плавающей запятой, поэтому вы должны объявить n1 как double.

Я рекомендую не использовать смесь команд c и c ++ (т. Е. cout и sscanf()). Он будет компилироваться в c ++, если синтаксис правильный, но я думаю, вам будет проще использовать cin вместо sscanf().

Вы также можете указать компилятору принять стандартное пространство имен (std), чтобы вам не приходилось писать std:: перед всеми вашими cout, cin, endl и т. д.

Пример: * * тысяча тридцать-один

#include <cstdlib> //atof
#include <iostream>   //cout, cin, endl
#include <string> //string, c_str()

using namespace std;   //now you don't have to write std::cout

int main() {
    float n1;
    string data;

    cin >> data;   //get input
    n1 = atof(data.c_str());   //convert data to const char* and make it a float
    cout << "Original data: " << data << endl;   //output
    cout << "Result: " << n1;
}

Обновленный, более умный, более полезный ответ:

Это всего лишь некоторые вещи, на которые я обратил внимание при проведении собственных тестов.

  1. Не используйте double, используйте float. Двойник не работал в моем исследовании.
  2. Когда вы использовали% .3f, вы показывали 3 знака после запятой целого числа, поэтому вы получаете 6.000
  3. n1 = sscanf(data, "%f", n1) неверно. Он скомпилируется, но программа должна вылететь (Это сделал для меня). Во-первых, sscanf() не возвращает найденное в данных число с плавающей точкой. Он возвращает количество заполненных переменных, поэтому не приведет к тому, что вы намереваетесь. Во-вторых, n1 необходимо сделать опорным параметром, чтобы это работало. Вы хотите редактировать исходную переменную n1, а не делать ее копию. Правильный синтаксис: sscanf(data, "%f", &n1);

Пример:

#include <cstdlib>
#include <cstdio>

using namespace std;

int main() {
    char data[5] = "6.35";
    float n1;

    sscanf(data, "%f", &n1);
    printf("%.3f" "%s", n1, "  ");
    n1 = atof(data);
    printf("%.3f", n1);
    return 0;
}
...