使用 `scanf()` 和 `%f` 的问题 (avr-gcc)

问题描述

(注意:在这个问题的早期版本中,我假设我使用了错误的引用方式。结果是一个不同的问题,我相应地对标题/问题进行了更改。)

我的代码打算用 avr-gcc 编译并在 ATmega168p 微控制器上运行。

我在 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]='\0';

    // 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(),它在字符缓冲区中搜索浮点值的开始和结束索引。函数 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 返回 0)。

我的问题:我将 buffer 的引用传递给 read_buffer_float 中的 find_float_in_buffer 的方式是否正确?我以为我终于明白了如何将指针或函数引用传递给函数,但我不确定这是否是您将函数中的指针传递给另一个函数的方式。

编辑:我在 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\0");

  char test[]="12.34\0";
  float testfloat=-1;
  sscanf(test,"%f",&testfloat);

  uartWriteString("teststring is:\t\0");
  uartWriteString(test);
  uartWriteString("\n\rscanned float is:\t\0");
  uartWriteFloat(testfloat);
  uartWriteString("\n\0");

  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 --versionavr-gcc.exe (GCC) 10.1.0

当我在我的开发系统上运行以下等效程序时,它可以工作。

#include <stdio.h>

int main() {
  printf("application started\n\r\0");

  char test[]="12.34\0";
  float testfloat=-1;
  sscanf(test,&testfloat);

  printf("teststring is:\t\0");
  printf(test);
  printf("\n\rscanned float is:\t\0");
  printf("%.2f",testfloat);
  printf("\n\0");
}

但是:当我将 "%.2f" 作为格式说明符(如评论中指出的那样无效)传递给 sscanf() 时,此版本失败并具有相同的行为。

解决方法

既然您已经强制编译器使用printf支持 float,您知道标准库的这个限制。

您也需要为 scanf() 执行此操作。请参阅文档。

avr-gcc -std=gnu99 -Wl,-u,vfprintf -lprintf_flt -Wl,vfscanf -lscanf_flt -lm -mmcu=atmega168p main.o -o main.elf

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...