将 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++ 命令(即cout
和sscanf()
)。如果语法正确,它将在 c++ 中编译,但我认为使用 cin
而不是 sscanf()
会更容易。
您可能还想告诉编译器采用标准命名空间 (std),这样您就不必在所有 cout
、cin
、endl
前面写上 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", &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", &n1);
我的atof
函数不会转换为浮动@ 987654359@ 值。 我已经更新了我的问题,关于遵循我的data
变量的过程,我正在尝试检查发生了什么,但如果我很好地应用了你的指示,我会忽略。非常感谢您的支持以上是关于将 char[] 转换为 float 或 double - c++的主要内容,如果未能解决你的问题,请参考以下文章
试图将 char 类型转换为 float 类型,但 gettng 分段错误
Java中怎么将Long类型转换成Integer或int类型?