【发布时间】: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 <sys/features.h>,然后再做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", &temp_freq);(您需要#include <inttypes.h>)。 -
@AdrianMole 我做过,忘了提。我会相应地更新问题。
-
如果您的库确实不支持
%lld,并且如果您决定“自己动手”,那么使用十六进制而不是十进制可能更容易。特别是,如果发送方总是发送正好 16 个十六进制数字,那么在接收方您可以执行类似long hi, lo; sscanf(buffer, "FOUT = %8lx%8lx Hz\r\n", &hi, &lo)后跟temp_freq = (int64_t)hi << 32 | lo的操作。