SSCANF 怎么会提供如此奇怪的结果?
How could SSCANF provide so strange results?
我正在与此代码进行为期 4 天的斗争:
unsigned long baudrate = 0;
unsigned char databits = 0;
unsigned char stop_bits = 0;
char parity_text[10];
char flowctrl_text[4];
const char xformat[] = "%lu,%hhu,%hhu,%[^,],%[^,]\n";
const char xtext[] = "115200,8,1,EVEN,NFC\n";
int res = sscanf(xtext, xformat, &baudrate, &databits, &stop_bits, (char*) &parity_text, (char*) &flowctrl_text);
printf("Res: %d\r\n", res);
printf("baudrate: %lu, databits: %hhu, stop: %hhu, \r\n", baudrate, databits, stop_bits);
printf("parity: %s \r\n", parity_text);
printf("flowctrl: %s \r\n", flowctrl_text);
它returns:
Res: 5
baudrate: 115200, databits: 0, stop: 1,
parity:
flowctrl: NFC
Databits 和 parity 缺失!
其实parity变量下的内存是'\0'VEN'\0',
看起来第一个字符以某种方式被 sscanf 程序覆盖了。
Return sscanf 的值为 5,这表明它能够解析输入。
我的配置:
- gccarmnoneeabi 7.2.1
- Visual Studio 代码 1.43.2
- PlatformIO 核心 4.3.1
- PlatformIO 主页 3.1.1
- 库 ST-STM 6.0.0 (Mbed 5.14.1)
- STM32F446RE(Nucleo-F446RE)
我试过了(没有成功):
- 使用 mbed RTOS 和不使用
进行编译
- 变量类型uint8_t、uint32_t
- gccarm 版本:6.3.1、8.3.1、9.2.1
- 使用另一个 IDE (CLion+PlatformIO)
- 在另一台计算机上编译(相同配置)
真正有帮助的是:
- 使变量静态化
- 在 Mbed 在线编译器中编译
sscanf 的行为整体上是非常不可预测的,混合变量的顺序或数据类型有时会有所帮助,但通常以输出中的另一个缺陷告终。
这让我花了比我愿意承认的时间更长的时间。但像大多数问题一样,它最终变得非常简单。
char parity_text[10];
char flowctrl_text[4];
需要改为:
char parity_text[10] = {0};
char flowctrl_text[5] = {0};
flowctrl_text 数组大小为 4,不足以容纳 "EVEN" 和 NULL 终止符。如果你将它的大小设置为 5,你应该没有问题。为了安全起见,我还将数组初始化为 0.
一旦我增加了大小,你现有的代码就出现了 0 个问题。让我知道这是否有帮助。
我正在与此代码进行为期 4 天的斗争:
unsigned long baudrate = 0;
unsigned char databits = 0;
unsigned char stop_bits = 0;
char parity_text[10];
char flowctrl_text[4];
const char xformat[] = "%lu,%hhu,%hhu,%[^,],%[^,]\n";
const char xtext[] = "115200,8,1,EVEN,NFC\n";
int res = sscanf(xtext, xformat, &baudrate, &databits, &stop_bits, (char*) &parity_text, (char*) &flowctrl_text);
printf("Res: %d\r\n", res);
printf("baudrate: %lu, databits: %hhu, stop: %hhu, \r\n", baudrate, databits, stop_bits);
printf("parity: %s \r\n", parity_text);
printf("flowctrl: %s \r\n", flowctrl_text);
它returns:
Res: 5
baudrate: 115200, databits: 0, stop: 1,
parity:
flowctrl: NFC
Databits 和 parity 缺失!
其实parity变量下的内存是'\0'VEN'\0', 看起来第一个字符以某种方式被 sscanf 程序覆盖了。
Return sscanf 的值为 5,这表明它能够解析输入。
我的配置:
- gccarmnoneeabi 7.2.1
- Visual Studio 代码 1.43.2
- PlatformIO 核心 4.3.1
- PlatformIO 主页 3.1.1
- 库 ST-STM 6.0.0 (Mbed 5.14.1)
- STM32F446RE(Nucleo-F446RE)
我试过了(没有成功):
- 使用 mbed RTOS 和不使用 进行编译
- 变量类型uint8_t、uint32_t
- gccarm 版本:6.3.1、8.3.1、9.2.1
- 使用另一个 IDE (CLion+PlatformIO)
- 在另一台计算机上编译(相同配置)
真正有帮助的是:
- 使变量静态化
- 在 Mbed 在线编译器中编译
sscanf 的行为整体上是非常不可预测的,混合变量的顺序或数据类型有时会有所帮助,但通常以输出中的另一个缺陷告终。
这让我花了比我愿意承认的时间更长的时间。但像大多数问题一样,它最终变得非常简单。
char parity_text[10];
char flowctrl_text[4];
需要改为:
char parity_text[10] = {0};
char flowctrl_text[5] = {0};
flowctrl_text 数组大小为 4,不足以容纳 "EVEN" 和 NULL 终止符。如果你将它的大小设置为 5,你应该没有问题。为了安全起见,我还将数组初始化为 0.
一旦我增加了大小,你现有的代码就出现了 0 个问题。让我知道这是否有帮助。