伙计们,我想知道float
函数中是否可以使用sprintf()
变量。
就像,如果我们写:
sprintf(str,"adc_read = %d \n",adc_read);
其中adc_read
是一个整数变量,它将存储字符串
<{1>}中的
"adc_read = 1023 \n"
(假设str
)
如何使用float变量代替整数?
答案 0 :(得分:47)
由于您使用的是嵌入式平台,因此您很可能无法使用printf()
样式函数提供全部功能。
假设你有浮动(仍然不一定是嵌入式东西),你可以使用类似的东西来模拟它:
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
。我发现以下网页似乎描述了在%f
语句here中使用printf()
所需执行的操作。
正如我最初所怀疑的那样,你需要做一些额外的工作来获得浮点支持。这是因为嵌入式东西很少需要浮点(至少没有我曾经做过的东西)。它涉及在makefile中设置额外的参数并与额外的库链接。
但是,由于需要处理常规输出格式,这可能会大大增加您的代码大小。如果你可以将你的浮动输出限制在4位小数或更少的位置,我建议把我的代码转换成一个函数并使用它 - 它可能会占用更少的空间。
如果该链接消失,您需要做的是确保您的gcc命令具有"-Wl,-u,vfprintf -lprintf_flt -lm
“。这转换为:
printf()
库。答案 1 :(得分:3)
这样的事情真的不容易:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char str[10];
float adc_read = 678.0123;
dtostrf( adc_read, 3, 4, temp );
sprintf(str,"adc_read = %10s \n", temp);
printf(temp);
答案 2 :(得分:2)
是的,你可以。但是,它取决于您链接的C库,您需要了解其后果。
由于您正在为嵌入式应用程序编程,因此请认识到为许多嵌入式体系结构模拟了浮点支持。在此浮点支持中进行编译将最终显着增加可执行文件的大小。
答案 3 :(得分:1)
不要指望sprintf(或任何其他带varargs的函数)自动转换任何东西。编译器不会尝试读取格式字符串并为您执行转换;在运行时,sprintf没有可用于确定堆栈内容的元信息;它只是弹出字节并将其解释为格式字符串给出的。 sprintf(myvar,“%0”,0);立即断裂。
所以:格式字符串和其他参数必须匹配!
答案 4 :(得分:0)
使用%f
修饰符:
sprintf (str, "adc_read = %f\n", adc_read);
例如:
#include <stdio.h>
int main (void)
{
float x = 2.5;
char y[200];
sprintf(y, "x = %f\n", x);
printf(y);
return 0;
}
产生这个:
x = 2.500000
答案 5 :(得分:0)
是的,当然,漂浮物并没有什么特别之处。您可以在printf()中使用格式字符串作为浮点数和任何其他数据类型。
修改强> 我试过这个示例代码:
float x = 0.61;
char buf[10];
sprintf(buf, "Test=%.2f", x);
printf(buf);
输出为:测试= 0.61
答案 6 :(得分:0)
是的,不。尽管其他一些回复说过,C编译器 需要执行sprintf()
和所有其他可变函数的转换,如下所示:
char
=&gt; int
short
=&gt; int
float
=&gt; double
(以及上述整数类型的有符号/无符号变体)
这恰恰是因为sprintf()
(和其他print()
- 家庭功能)没有它就无法使用。 (当然,they're pretty unusable as it is。)
但是您不能假设任何其他转换,并且您的代码将具有未定义的行为 - 阅读:崩溃! - 如果你这样做。
答案 7 :(得分:0)
查看适合您平台的sprintf文档。通常为%f或%e。唯一能找到明确答案的地方就是文件......如果没有证件,你可以联系供应商。
它是什么平台?有人可能已经知道文档在哪里...... :)
答案 8 :(得分:0)
不要这样做; C / C ++中的整数总是向下舍入,因此不需要使用floor函数。
char str[100];
int d1 = value;
最好使用
int d1 = (int)(floor(value));
然后你不会得到整数部分(68.9999999999999999变为69.00 ..)。 68.09999847而不是68.1很难避免 - 任何浮点格式的精度都有限。
答案 9 :(得分:0)
%g 可以这样做:
#include <stdio.h>
int main() {
float w = 234.567;
char x[__SIZEOF_FLOAT__];
sprintf(x, "%g", w);
puts(x);
}
答案 10 :(得分:0)
许多嵌入式系统的snprintf函数有限,无法处理浮点数。我写了这个,它有效地解决了问题。我选择使用64位无符号整数来处理较大的浮点数,因此请随时将其减少到16位或资源有限的任何需要。
#include <stdio.h> // for uint64_t support.
int snprintf_fp( char destination[], size_t available_chars, int decimal_digits,
char tail[], float source_number )
{
int chars_used = 0; // This will be returned.
if ( available_chars > 0 )
{
// Handle a negative sign.
if ( source_number < 0 )
{
// Make it positive
source_number = 0 - source_number;
destination[ 0 ] = '-';
++chars_used;
}
// Handle rounding
uint64_t zeros = 1;
for ( int i = decimal_digits; i > 0; --i )
zeros *= 10;
uint64_t source_num = (uint64_t)( ( source_number * (float)zeros ) + 0.5f );
// Determine sliding divider max position.
uint64_t div_amount = zeros; // Give it a head start
while ( ( div_amount * 10 ) <= source_num )
div_amount *= 10;
// Process the digits
while ( div_amount > 0 )
{
uint64_t whole_number = source_num / div_amount;
if ( chars_used < (int)available_chars )
{
destination[ chars_used ] = '0' + (char)whole_number;
++chars_used;
if ( ( div_amount == zeros ) && ( zeros > 1 ) )
{
destination[ chars_used ] = '.';
++chars_used;
}
}
source_num -= ( whole_number * div_amount );
div_amount /= 10;
}
// Store the zero.
destination[ chars_used ] = 0;
// See if a tail was specified.
size_t tail_len = strlen( tail );
if ( ( tail_len > 0 ) && ( tail_len + chars_used < available_chars ) )
{
for ( size_t i = 0; i <= tail_len; ++i )
destination[ chars_used + i ] = tail[ i ];
chars_used += tail_len;
}
}
return chars_used;
}
main()
{
#define TEMP_BUFFER_SIZE 30
char temp_buffer[ TEMP_BUFFER_SIZE ];
char degrees_c[] = { (char)248, 'C', 0 };
float float_temperature = 26.845f;
int len = snprintf_fp( temp_buffer, TEMP_BUFFER_SIZE, 2, degrees_c, float_temperature );
}
答案 11 :(得分:0)
类似于上面的paxdiablo。 将此代码插入更广泛的应用程序中,可与STM32 NUCLEO-F446RE配合使用。
#include <stdio.h>
#include <math.h>
#include <string.h>
void IntegFract(char *pcIntegStr, char *pcFractStr, double dbValue, int iPrecis);
main()
{
char acIntegStr[9], acFractStr[9], char counter_buff[30];
double seconds_passed = 123.0567;
IntegFract(acIntegStr, acFractStr, seconds_passed, 3);
sprintf(counter_buff, "Time: %s.%s Sec", acIntegStr, acFractStr);
}
void IntegFract(char *pcIntegStr, char *pcFractStr, double dbValue, int
iPrecis)
{
int iIntegValue = dbValue;
int iFractValue = (dbValue - iIntegValue) * pow(10, iPrecis);
itoa(iIntegValue, pcIntegStr, 10);
itoa(iFractValue, pcFractStr, 10);
size_t length = strlen(pcFractStr);
char acTemp[9] = "";
while (length < iPrecis)
{
strcat(acTemp, "0");
length++;
}
strcat(acTemp, pcFractStr);
strcpy(pcFractStr, acTemp);
}
counter_buff将包含123.056。
答案 12 :(得分:-2)
是的,使用%f