将 `scanf()` 与 `%f` (avr-gcc) 结合使用时出现问题
Problem using `scanf()` with `%f` (avr-gcc)
(注意:在这个问题的早期版本中,我假设我以错误的方式使用了引用。结果是一个不同的问题,我相应地对 title/question 进行了更改。)
我的代码打算在 ATmega168p 微控制器上使用 avr-gcc
和 运行 进行编译。
我在 C 中有以下函数,它应该从缓冲区(字符数组)解析浮点值并将其分配给相应的浮点变量:
void read_float_from_buffer(float *var, char *buffer, uint8_t start, uint8_t end) {
char val_buf[8];
// transfer characters representing float to a temporary buffer
uint8_t p=0;
for (uint8_t i=start;i<=end && p<7;i++) {
val_buf[p++]=buffer[i];
}
val_buf[p]='[=10=]';
// perform sscanf on this temporary buffer
float buf=-1;
if(sscanf(val_buf, "%.2f", &buf)==1) // this fails, sscanf returns 0
*var=buf;
}
我有另一个函数 find_float_in_buffer()
,它在 char 缓冲区中搜索浮点值的开始和结束索引。在此函数内调用函数 read_float_from_buffer()
:
float a_float_variable=0.;
void find_float_in_buffer(char *buffer) {
uint8_t start,end=0;
/*
I do some magic here to find out where my float string starts and ends
*/
read_buffer_float(&a_float_variable,buffer,start,end);
}
根据我的理解,这应该可行,但由于某种原因,扫描 val_buf
临时缓冲区失败 (sscanf returns 0)。
我的问题:我将 buffer
的引用传递给 find_float_in_buffer
中的 read_buffer_float
的方式是否正确?我想我终于明白了如何将指针或引用传递给函数,但我不确定这是否是将函数中的指针传递给另一个函数的方式。
编辑: 我正在 运行 在 Atmel 微控制器上编写此代码并使用 avr-gcc
.
进行编译
编辑 2: 我删除了整个固件并提出了以下 MWE:
#define F_CPU 8000000UL
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <util/delay.h>
#include "src/peripheral-core/uart.c"
int main() {
_delay_ms(200);
uart_init();
uartWriteString("application started\n\r[=12=]");
char test[]="12.34[=12=]";
float testfloat=-1;
sscanf(test, "%f", &testfloat);
uartWriteString("teststring is:\t[=12=]");
uartWriteString(test);
uartWriteString("\n\rscanned float is:\t[=12=]");
uartWriteFloat(testfloat);
uartWriteString("\n[=12=]");
for (;;) {
_delay_ms(1000);
}
}
对我来说,这会打印:
application started
teststring is: 12.34
scanned float is: -1.000
要构建 .hex
文件,我 运行 使用此命令:
avr-gcc -std=gnu99 -c -Os -Wall -mmcu=atmega168p main.c -o main.o
avr-gcc -std=gnu99 -Wl,-u,vfprintf -lprintf_flt -lm -mmcu=atmega168p main.o -o main.elf
avr-objcopy -O ihex -j .data -j .text main.elf main.hex
AVR-GCC 版本:
avr-gcc --version
给出 avr-gcc.exe (GCC) 10.1.0
当我在我的开发系统上 运行 下面的等价物时,它起作用了。
#include <stdio.h>
int main() {
printf("application started\n\r[=15=]");
char test[]="12.34[=15=]";
float testfloat=-1;
sscanf(test, "%f", &testfloat);
printf("teststring is:\t[=15=]");
printf(test);
printf("\n\rscanned float is:\t[=15=]");
printf("%.2f",testfloat);
printf("\n[=15=]");
}
但是: 当我将 "%.2f"
作为格式说明符传递给 sscanf()
时(如评论中指出的那样无效),此版本失败具有相同的行为。
因为您已经强制编译器使用 printf
库 并且 支持 float
,您知道标准库的这个限制。
您也需要为 scanf()
执行此操作。请参阅文档。
avr-gcc -std=gnu99 -Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm -mmcu=atmega168p main.o -o main.elf
(注意:在这个问题的早期版本中,我假设我以错误的方式使用了引用。结果是一个不同的问题,我相应地对 title/question 进行了更改。)
我的代码打算在 ATmega168p 微控制器上使用 avr-gcc
和 运行 进行编译。
我在 C 中有以下函数,它应该从缓冲区(字符数组)解析浮点值并将其分配给相应的浮点变量:
void read_float_from_buffer(float *var, char *buffer, uint8_t start, uint8_t end) {
char val_buf[8];
// transfer characters representing float to a temporary buffer
uint8_t p=0;
for (uint8_t i=start;i<=end && p<7;i++) {
val_buf[p++]=buffer[i];
}
val_buf[p]='[=10=]';
// perform sscanf on this temporary buffer
float buf=-1;
if(sscanf(val_buf, "%.2f", &buf)==1) // this fails, sscanf returns 0
*var=buf;
}
我有另一个函数 find_float_in_buffer()
,它在 char 缓冲区中搜索浮点值的开始和结束索引。在此函数内调用函数 read_float_from_buffer()
:
float a_float_variable=0.;
void find_float_in_buffer(char *buffer) {
uint8_t start,end=0;
/*
I do some magic here to find out where my float string starts and ends
*/
read_buffer_float(&a_float_variable,buffer,start,end);
}
根据我的理解,这应该可行,但由于某种原因,扫描 val_buf
临时缓冲区失败 (sscanf returns 0)。
我的问题:我将 buffer
的引用传递给 find_float_in_buffer
中的 read_buffer_float
的方式是否正确?我想我终于明白了如何将指针或引用传递给函数,但我不确定这是否是将函数中的指针传递给另一个函数的方式。
编辑: 我正在 运行 在 Atmel 微控制器上编写此代码并使用 avr-gcc
.
编辑 2: 我删除了整个固件并提出了以下 MWE:
#define F_CPU 8000000UL
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <util/delay.h>
#include "src/peripheral-core/uart.c"
int main() {
_delay_ms(200);
uart_init();
uartWriteString("application started\n\r[=12=]");
char test[]="12.34[=12=]";
float testfloat=-1;
sscanf(test, "%f", &testfloat);
uartWriteString("teststring is:\t[=12=]");
uartWriteString(test);
uartWriteString("\n\rscanned float is:\t[=12=]");
uartWriteFloat(testfloat);
uartWriteString("\n[=12=]");
for (;;) {
_delay_ms(1000);
}
}
对我来说,这会打印:
application started
teststring is: 12.34
scanned float is: -1.000
要构建 .hex
文件,我 运行 使用此命令:
avr-gcc -std=gnu99 -c -Os -Wall -mmcu=atmega168p main.c -o main.o
avr-gcc -std=gnu99 -Wl,-u,vfprintf -lprintf_flt -lm -mmcu=atmega168p main.o -o main.elf
avr-objcopy -O ihex -j .data -j .text main.elf main.hex
AVR-GCC 版本:
avr-gcc --version
给出 avr-gcc.exe (GCC) 10.1.0
当我在我的开发系统上 运行 下面的等价物时,它起作用了。
#include <stdio.h>
int main() {
printf("application started\n\r[=15=]");
char test[]="12.34[=15=]";
float testfloat=-1;
sscanf(test, "%f", &testfloat);
printf("teststring is:\t[=15=]");
printf(test);
printf("\n\rscanned float is:\t[=15=]");
printf("%.2f",testfloat);
printf("\n[=15=]");
}
但是: 当我将 "%.2f"
作为格式说明符传递给 sscanf()
时(如评论中指出的那样无效),此版本失败具有相同的行为。
因为您已经强制编译器使用 printf
库 并且 支持 float
,您知道标准库的这个限制。
您也需要为 scanf()
执行此操作。请参阅文档。
avr-gcc -std=gnu99 -Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm -mmcu=atmega168p main.o -o main.elf