Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using floats with sprintf() in embedded C

Guys, I want to know if float variables can be used in sprintf() function.

Like, if we write:

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

where adc_read is an integer variable, it will store the string

"adc_read = 1023 \n"

in str (assuming that adc_read = 1023)

How can I use a float variable in place of integer?

like image 812
aditya Avatar asked May 25 '09 08:05

aditya


People also ask

How do I print a float in sprintf?

float fl = (glove[1] / 22.8) - 0.85; char minStr[100];//cnt min sec temp skinHi skinLO beat move print"fl = "; println(fl,2); sprintf(minStr,"%1.2f ,%02d:%02d ,%03d ,%03d ,%03d ,%03d ,%03d", fl,hour,minute,oneMin.

What is sprintf () function in C?

sprintf() in C sprintf stands for "string print". In C programming language, it is a file handling function that is used to send formatted output to the string. Instead of printing on console, sprintf() function stores the output on char buffer that is specified in sprintf.

Why do we use sprintf in C programming?

If successful, it returns the total number of characters written excluding null-character appended in the string, in case of failure a negative number is returned . sprintf stands for “String print”. Instead of printing on console, it store output on char buffer which are specified in sprintf.

What is the difference between sprintf and Snprintf?

The snprintf() function is identical to the sprintf() function with the addition of the n argument, which indicates the maximum number of characters (including the ending null character) to be written to buffer.


1 Answers

Since you're on an embedded platform, it's quite possible that you don't have the full range of capabilities from the printf()-style functions.

Assuming you have floats at all (still not necessarily a given for embedded stuff), you can emulate it with something like:

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); 

You'll need to restrict how many characters come after the decimal based on the sizes of your integers. For example, with a 16-bit signed integer, you're limited to four digits (9,999 is the largest power-of-ten-minus-one that can be represented).

However, there are ways to handle this by further processing the fractional part, shifting it by four decimal digits each time (and using/subtracting the integer part) until you have the precision you desire.


Update:

One final point you mentioned that you were using avr-gcc in a response to one of the other answers. I found the following web page that seems to describe what you need to do to use %f in your printf() statements here.

As I originally suspected, you need to do some extra legwork to get floating point support. This is because embedded stuff rarely needs floating point (at least none of the stuff I've ever done). It involves setting extra parameters in your makefile and linking with extra libraries.

However, that's likely to increase your code size quite a bit due to the need to handle general output formats. If you can restrict your float outputs to 4 decimal places or less, I'd suggest turning my code into a function and just using that - it's likely to take up far less room.

In case that link ever disappears, what you have to do is ensure that your gcc command has "-Wl,-u,vfprintf -lprintf_flt -lm". This translates to:

  • force vfprintf to be initially undefined (so that the linker has to resolve it).
  • specify the floating point printf() library for searching.
  • specify the math library for searching.
like image 186
paxdiablo Avatar answered Sep 17 '22 15:09

paxdiablo