Arduino中的sprintf函数无法格式化浮点数。

67

我有这个Arduino的草图,

char temperature[10];
float temp = 10.55;
sprintf(temperature,"%f F", temp);
Serial.println(temperature);

温度打印为

? F

你对如何格式化这个float有什么想法吗?我需要它成为一个char字符串。

4个回答

145

由于一些性能原因,%f在Arduino的sprintf()实现中没有包含。更好的选择是使用dtostrf() - 将浮点数值转换为C风格的字符串,方法签名如下:

char *dtostrf(double val, signed char width, unsigned char prec, char *s)

使用此方法将其转换为C风格字符串,然后使用sprintf,例如:

char str_temp[6];

/* 4 is mininum width, 2 is precision; float value is copied onto str_temp*/
dtostrf(temp, 4, 2, str_temp);
sprintf(temperature,"%s F", str_temp);
您可以更改最小宽度和精度,以匹配您要转换的浮点数。

4
在我的情况下工作得很好。赞! - Fahad Siddiqui
只是提醒,你的缓冲区 str_temp 的宽度非常紧凑,只有6个字符。 - Paulus

9

如前所述,Arduino的sprintf不支持浮点数。

字符串类

Arduino有自己的String类。

String value = String(3.14);

那么,
char *result = value.c_str();

String类参考,链接在上方

构造一个String类的实例。有多个版本可以从不同的数据类型(即将它们格式化为字符序列)构造字符串,包括:

  • 用双引号括起来的字符常量(即char数组)
  • 单引号括起来的单个常量字符
  • 另一个String对象的实例
  • 常量整数或长整数
  • 使用指定基数的常量整数或长整数
  • 整数或长整数变量
  • 使用指定基数的整数或长整数变量
  • 使用指定小数位的浮点数或双精度数

3
上方指针的重要提示:当您修改String对象或将其销毁时,先前由c_str()返回的任何指针都会变为无效,不应再继续使用。 - JrBenito
1
我想说,显然,但是对于新手来说,这是一个非常好的Arduino编程建议。 - Cameron Lowell Palmer
Arduino的String类没有接受浮点数的方法。这只能工作是因为它将其转换为整数。 - Cerin
1
@CameronLowellPalmer 你说得对,是我的错误。最新的Arduino版本确实包括了对double和float类型的String支持。我正在使用Ubuntu附带的旧版本,它不支持这个功能,当我尝试将float传递给String()时会抛出编译器错误。 - Cerin
注意:对于新手来说,关于String类的一个繁琐但重要的提示:它动态分配/释放堆内存,因此从长远来看,它是“堆碎片化”的主要生成器。尽量限制其使用,更喜欢C风格的字符串。有关Arduino内存注意事项的更多信息 - Niki Romagnoli
3
String(3.1434, 4)中的第二个参数可以设置小数点后的精度,例如将数字3.1434保留4位小数。 - Orkhan Alikhanov

2

我曾经花费了几个小时来解决这个问题,但最终还是成功了。这里使用的是Platformio提供的现代Espressif C++,我的目标MCU是ESP32。

我想要显示一个前缀标签、浮点/整数值,然后是单位,全部都在一行内。

由于我正在使用OLED显示器,所以无法依赖于单独的Serial.print()语句。

以下是我的代码示例:

  int strLenLight = sizeof("Light ADC: 0000");
  int strLenTemp = sizeof("Temp: 000.0 °C");
  int strLenHumd = sizeof("Humd: 00.0 %");

  char displayLight[strLenLight] = "Light ADC: ";
  char displayTemp[strLenTemp] = "Temp: ";
  char displayHumd[strLenHumd] = "Humd: ";

  snprintf(strchr(displayLight, '\0'), sizeof(displayLight), "%d", light_value);
  snprintf(strchr(displayTemp, '\0'), sizeof(displayTemp), "%.1f °C", temperature); 
  snprintf(strchr(displayHumd, '\0'), sizeof(displayHumd), "%.1f %%", humidity); 

  Serial.println(displayLight);
  Serial.println(displayTemp);
  Serial.println(displayHumd);

这将显示:

Light ADC: 1777
Temp: 25.4 °C
Humd: 55.0 %

0

dtostrf()已经被弃用,并且并不在每个板子的核心平台上存在。 另一方面,在AVR平台上,sprintf()无法格式化浮点数!


默认链接的sprintf()不支持%f,但如果需要,可以链接完整版本的sprintf() - Gerhard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接