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

Posted

技术标签:

【中文标题】将 char[] 转换为 float 或 double - c++【英文标题】:Converting char[] to float or double - c++ 【发布时间】:2018-05-11 22:05:16 【问题描述】:

UPDATE根据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,但 atof 删除小数部分或不包括浮点数据。

总而言之,我可能没有很好地将参数传递给atof 函数(我的n1 变量是 float )。 关于sscanf 函数,我将&n1 传递给sscanf,就像数据的引用参数一样,用atof 进行转换,但这不起作用

我得到相同的结果。 我在想这是可能的,虽然我理解TNTFreaks 的说明我没有以正确的方式应用它?

我做错了什么?

【问题讨论】:

char data="6.35"; 不会编译。不清楚你在问什么。 问题在于您的语言环境。见***.com/questions/13919817/… 您确定将代码正确放入问题中吗?无论我对代码做什么,我都会遇到编译错误:godbolt.org/g/GQ86Nk sscanf() and locales. How does one really parse things like "3.14"?的可能重复 大多数实现还不支持它,但与语言环境无关的解析现在是 C++17 标准库的一部分:en.cppreference.com/w/cpp/utility/from_chars。 【参考方案1】:

首先,char 是一种变量类型,它只能包含一个字符或一个字符数组,而不是字符串。您可能指的是const char* data = "6.35",它是一个c 风格的字符串,而atof() 函数需要作为输入。如果您不遵循我在下面的建议并且仍想使用sscanf() 而不是cin,我只会使用data 作为const char*

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

atof 返回一个双精度而不是浮点数,因此您应该将 n1 声明为双精度。

我建议不要混合使用 c 和 c++ 命令(即coutsscanf())。如果语法正确,它将在 c++ 中编译,但我认为使用 cin 而不是 sscanf() 会更容易。

您可能还想告诉编译器采用标准命名空间 (std),这样您就不必在所有 coutcinendl 前面写上 std::的等。

例子:

#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;

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

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

    不要使用双精度,使用浮点数。 Double 在我的研究中不起作用。 当您使用 %.3f 时,您会显示整数的 3 位小数,因此您会得到 6.000 n1 = sscanf(data, "%f", n1) 不正确。它将编译,但程序应该崩溃。 (它对我有用)。首先,sscanf() 不返回在数据中找到的浮点数。它返回填充的变量数,因此不会产生您想要的结果。其次,需要将n1 作为参考参数才能使其正常工作。您想编辑原始变量 n1 而不是复制它。正确的语法是:sscanf(data, "%f", &amp;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;

【讨论】:

sscanf 函数不仅仅是 C 中的 cin 等价物,或者类似的东西。您可以将scanf 简化为那样,但sscanf 适用于程序内存中已经存在的数据,而不是标准输入。它更像是 stringstreams 的等价物,除了 stringstreams 在许多(大多数?全部?)情况下有相当多的运行时开销。 将数据声明为字符串这是个好主意,但我声明的 char data 变量就是这种方式 char data[CMD_LEN + 1];我已经更新了一些我的问题......只是以防万一),这个data变量被传递给serial_read函数,这里是一个接收这个参数的指针。然后声明像字符串这样的数据,这对我来说不是替代品...... :( @bgarcial 我在这个问题上丢失了我的笔记,但我输入了我能记住的内容。当我发现/记住它们时,我会更新更多信息。 @TNTFreaks,如果您需要有关它的一些信息,我将等待处理。 嗨@TNTFreaks 我按照你指导我的说明进行操作,但我的结果与将n1 类似引用参数应用于sscanf(data, "%f", &amp;n1); 我的atof 函数不会转换为浮动@ 987654359@ 值。 我已经更新了我的问题,关于遵循我的data 变量的过程,我正在尝试检查发生了什么,但如果我很好地应用了你的指示,我会忽略。非常感谢您的支持

以上是关于将 char[] 转换为 float 或 double - c++的主要内容,如果未能解决你的问题,请参考以下文章

c语言里怎么把float转换为char型?

试图将 char 类型转换为 float 类型,但 gettng 分段错误

C++中,如何讲CHAR数组转换成FLOAT型数据。

Java中怎么将Long类型转换成Integer或int类型?

Arduino中数据类型转换 float/double转换为char 亲测好使,dtostrf()函数

Arduino中数据类型转换 float/double转换为char 亲测好使,dtostrf()函数