【问题标题】:Can Arduino ESP8266 sscanf handle %lld?Arduino ESP8266 sscanf 可以处理 %lld 吗?
【发布时间】:2021-10-14 23:14:14
【问题描述】:

我在使用 Arduino ESP8266 和 sscanf 函数时遇到问题。我正在尝试从我从串口收到的字符串中解析一个 64 位整数,如下所示:

int64_t temp_freq = 0;
sscanf(buffer, "FOUT = %lld Hz\r\n", &temp_freq);

编辑:我也尝试了`"FOUT = %" SCNd64 " Hz\r\n",结果相同

我知道我从串行端口得到了正确的字符串,因为我的代码检查我是否收到了该特定类型的消息被触发并正在运行。

我还可以确认 %lld 正在使用 Serial.printf(),所以我假设它也适用于 sscanf

但是,如果字符串中有一个 > 2^31 - 1 的值,我会将 2^31 - 1 写入我的 int64_t 变量中。例如,"FOUT = 18010000000 Hz\r\n" 在我的 int64_t 变量中给了我 2,147,483,647。

我是在错误地使用sscanf,还是在平台上没有正确实现?

我同时使用以下解决方法:

int64_t temp_freq = 0;
char temp_buf[30] = {0x00};
sscanf(buffer, "FOUT = %s Hz\r\n", &temp_buf);
for (int i = 0; i < strlen(temp_buf); ++i) {
  temp_freq *= 10;
  temp_freq += temp_buf[i] - '0';
}

但我宁愿使用标准的工作方式和正确的方式,以免我不得不在任何地方维护我的手动解决方案。

PS:我标记为 C++ 和 C,因为它在技术上是 Arduino 上的 C++,但我编写的代码看起来更像 C,并且使用 C 的 sscanf 而不是 stringstream 或类似 C++ 的东西。

【问题讨论】:

  • 如果你先做#include &lt;sys/features.h&gt;,然后再做printf("%s\n", _NEWLIB_VERSION),它会输出什么?或printf("%d\n", _WANT_IO_LONG_LONG).
  • printf("%s\n", _NEWLIB_VERSION); 给出2.2.0。由于_WANT_IO_LONG_LONG 未在当前范围内声明,printf("%s\n", _WANT_IO_LONG_LONG); 导致编译错误。
  • 您是否尝试过使用sscanf(buffer, "FOUT = %" SCNd64 " Hz\r\n", &amp;temp_freq);(您需要#include &lt;inttypes.h&gt;)。
  • @AdrianMole 我做过,忘了提。我会相应地更新问题。
  • 如果您的库确实不支持%lld,并且如果您决定“自己动手”,那么使用十六进制而不是十进制可能更容易。特别是,如果发送方总是发送正好 16 个十六进制数字,那么在接收方您可以执行类似 long hi, lo; sscanf(buffer, "FOUT = %8lx%8lx Hz\r\n", &amp;hi, &amp;lo) 后跟 temp_freq = (int64_t)hi &lt;&lt; 32 | lo 的操作。

标签: c++ c arduino scanf


【解决方案1】:

是不是在平台上没有正确实现?

您的工具链正在使用 newlib 作为 C 标准库实现,并且很可能您正在使用它的 nano 版本。 Newlib-nano 在printf/scanf 系列函数中不支持long long

你可以:

  • 使用完整的 newlib 版本而不是 nano 版本。如果是gcc 编译器,请-specs=nano.specs-lnano 传递给您的编译器选项。
  • 使用不同的标准库或重新编译 newlib 并启用该选项。
  • 自己重新实现所需的功能。

请注意,将%lldint64_t 一起使用在技术上可能是错误的——您应该使用inttypes.h 中的SCNd64

【讨论】:

  • %lld 有什么问题?谁说你必须使用SCNd64
  • 没有错,只是不那么便携。在我使用的特定芯片上SCNd64 is probably defined as %lld, since int64_t` 是long long int 的类型定义。 SCNd64 将在所有使用 int64_t 的平台上做正确的事情,而不仅仅是在 int64_tlong long int 的 typedef 的 32 位平台上。
  • @SteveSummit:%lld 需要 long long intSCNd64 需要 int64_t。使用%lld 扫描到uint64_t 是假设long long intint64_t 在所有将运行该代码段的平台上都是相同的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-08
相关资源
最近更新 更多