将char []转换为float或double - c ++

时间:2018-05-11 22:05:17

标签: c++ type-conversion atof

根据 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

1,000值是我得到的data值1.86,但是除去小数部分或不包括foat数据。

总之,我可能没有将参数传递给atof函数,(我的n1变量是浮点数)。 关于sscanf函数,我将&amp; n1传递给sscanf,就像数据的参考参数一样,用atof进行转换,但这不起作用

我得到了相同的结果。 我认为这是可能的,虽然我理解TNTFreaks说明我不是以正确的方式应用它?

我做错了什么?

1 个答案:

答案 0 :(得分:7)

首先,char是一种变量,只能包含一个或一个字符数组而不是一个字符串。您可以将const char* data = "6.35"表示为c样式字符串以及atof()函数需要作为输入的内容。如果您不遵循我的建议,我只会将data用作const char*,但仍然希望使用sscanf()代替cin

在c ++中使用字符串比使用const char*或char数组更容易。我会将数据声明为字符串,获取输入,然后使用const char*将其转换为c_str(),以便atof()可以使用它。

atof返回一个double而不是float,因此你应该将n1声明为double。

我建议不要混合使用c和c ++命令(即coutsscanf())。如果语法正确,它将用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; } 等等。

示例:

n1 = sscanf(data, "%f", n1)

更新,更智能,更实用的答案:

这些只是我在做自己的一些测试时注意到的一些事情。

  1. 不要使用double,请使用float。 Double在我的研究中没有用。
  2. 当你使用%.3f时,你显示整数的3位小数,这就是为什么你得到6.000
  3. 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; }
  4. 示例:

    #include "SpinLock.h"
    #include <iostream>
    
    using namespace LockFree;
    using namespace std;
    
    void tSpinWait::Lock(tSpinLock &LockObj)
    {
        m_iterations = 0;
        while(true)
        {
            // A thread alreading owning the lock shouldn't be allowed to wait to acquire the lock - reentrant safe
            if(LockObj.dest == GetCurrentThreadId())
                break;
            /*
              Spinning in a loop of interlockedxxx calls can reduce the available memory bandwidth and slow
              down the rest of the system. Interlocked calls are expensive in their use of the system memory
              bus. It is better to see if the 'dest' value is what it is expected and then retry interlockedxx.
            */
            if(InterlockedCompareExchange(&LockObj.dest, LockObj.exchange, LockObj.compare) == 0)
            {
                //assign CurrentThreadId to dest to make it re-entrant safe
                LockObj.dest = GetCurrentThreadId();
                // lock acquired 
                break;          
            }
    
            // spin wait to acquire 
            while(LockObj.dest != LockObj.compare)
            {
                if(HasThreasholdReached())
                {
                    if(m_iterations + YIELD_ITERATION >= MAX_SLEEP_ITERATION)
                        Sleep(0);
    
                    if(m_iterations >= YIELD_ITERATION && m_iterations < MAX_SLEEP_ITERATION)
                    {
                        m_iterations = 0;
                        SwitchToThread();
                    }
                }
                // Yield processor on multi-processor but if on single processor then give other thread the CPU
                m_iterations++;
                if(Helper::GetNumberOfProcessors() > 1) { YieldProcessor(/*no op*/); }
                else { SwitchToThread(); }              
            }               
        }
    }
    //
    
    void tSpinWait::Unlock(tSpinLock &LockObj)
    {
        if(LockObj.dest != GetCurrentThreadId())
            throw std::runtime_error("Unexpected thread-id in release");
        // lock released
        InterlockedCompareExchange(&LockObj.dest, LockObj.compare, GetCurrentThreadId());   
    }