在嵌入式C中使用带有sprintf()的浮点数

大家好,我想知道float变量是否可以在sprintf()函数中使用。

就像,如果我们写:

 sprintf(str,"adc_read = %d \n",adc_read); 

其中adc_read是一个整数变量,它将存储该字符串

"adc_read = 1023 \n"

str (假设adc_read = 1023

如何使用float变量代替整数?

由于您使用的是嵌入式平台,因此您很可能无法获得printf()样式函数的全部function。

假设你有浮动(仍然不一定是嵌入式东西),你可以用以下方法模拟它:

 char str[100]; float adc_read = 678.0123; char *tmpSign = (adc_read < 0) ? "-" : ""; float tmpVal = (adc_read < 0) ? -adc_read : adc_read; int tmpInt1 = tmpVal; // Get the integer (678). float tmpFrac = tmpVal - tmpInt1; // Get fraction (0.0123). int tmpInt2 = trunc(tmpFrac * 10000); // Turn into integer (123). // Print as parts, note that you need 0-padding for fractional bit. sprintf (str, "adc_read = %s%d.%04d\n", tmpSign, tmpInt1, tmpInt2); 

您需要根据整数的大小限制小数点后的字符数。 例如,对于16位有符号整数,您将被限制为四位数(9,999是可以表示的最大十次幂的幂)。

但是,有一些方法可以通过进一步处理小数部分来处理这个问题,每次将它移动四位小数(并使用/减去整数部分),直到你有所需的精度。


更新:

最后一点你提到你在回答其中一个答案时使用的是avr-gcc 。 我发现以下网页似乎描述了在printf()语句中使用%f所需要做的事情。

正如我最初所怀疑的那样,你需要做一些额外的工作来获得浮点支持。 这是因为嵌入式东西很少需要浮点(至少没有我曾经做过的东西)。 它涉及在makefile中设置额外的参数并与额外的库链接。

但是,由于需要处理常规输出格式,这可能会大大增加您的代码大小。 如果你可以将浮点输出限制在4位小数或更少,我建议将我的代码转换为函数并使用它 - 它可能会占用更少的空间。

如果链接消失,您需要做的是确保您的gcc命令具有"-Wl,-u,vfprintf -lprintf_flt -lm ”。 这意味着:

  • 强制vfprintf最初是未定义的(以便链接器必须解析它)。
  • 指定用于搜索的浮点printf()库。
  • 指定用于搜索的数学库。

这样的事情真的不容易:

 #include  #include  #include  char str[10]; float adc_read = 678.0123; dtostrf( adc_read, 3, 4, temp ); sprintf(str,"adc_read = %10s \n", temp); printf(temp); 

是的你可以。 但是,它取决于您链接的C库,您需要了解其后果。

由于您是针对嵌入式应用程序进行编程,因此请认识到为许多嵌入式体系结构模拟了浮点支持。 在此浮点支持中进行编译将最终显着增加可执行文件的大小。

不要指望sprintf(或任何其他带varargs的函数)自动转换任何东西。 编译器不会尝试读取格式字符串并为您执行转换; 在运行时,sp​​rintf没有可用的元信息来确定堆栈中的内容; 它只是弹出字节并将其解释为格式字符串给出的。 sprintf(myvar,“%0”,0); 立即段错误。

所以:格式字符串和其他参数必须匹配!

是的,当然,漂浮物没什么特别的。 您可以在printf()中使用格式字符串作为浮点数和任何其他数据类型。

编辑我试过这个示例代码:

 float x = 0.61; char buf[10]; sprintf(buf, "Test=%.2f", x); printf(buf); 

输出为:测试= 0.61

使用%f修饰符:

 sprintf (str, "adc_read = %f\n", adc_read); 

例如:

 #include  int main (void) { float x = 2.5; char y[200]; sprintf(y, "x = %f\n", x); printf(y); return 0; } 

收益率:

x = 2.500000

查看适用于您的平台的sprintf文档。 通常为%f或%e。 唯一能找到明确答案的地方就是文件……如果没有证件,你可以联系供应商。

它是什么平台? 有人可能已经知道文档的位置…… 🙂

是的,不。 尽管其他一些回复说过,但C编译器需要为sprintf()和所有其他可变函数执行转换,如下所示:

  • char => int
  • short => int
  • float => double

(以及上述整数类型的有符号/无符号变体)

它之所以这样做是因为没有它, sprintf() (和其他print()家庭function)将无法使用。 (当然, 它们几乎无法使用 。)

但你不能假设任何其他转换,并且你的代码将有未定义的行为 – 阅读:崩溃! – 如果你这样做

不要这样做; C / C ++中的整数总是向下舍入,因此不需要使用floor函数。

 char str[100]; int d1 = value; 

更好用

 int d1 = (int)(floor(value)); 

然后你不会得到整数部分(68.9999999999999999变为69.00 ..)。 68.09999847而不是68.1很难避免 – 任何浮点格式的精度都有限。

%g可以这样做:

 #include  int main() { float w = 234.567; char x[__SIZEOF_FLOAT__]; sprintf(x, "%g", w); puts(x); } 

是的,使用%f