Formatting data for use in displays

All,

I have a 3.5" TFT device and I want to print some numbers on the screen (nice easy proportional fonts), but I don't want "stray characters" upon are redraw if the number size is different).

for example data = 31.2 lcd.print(data,1); // prints 31.2 data = 0.1 lcd.print(data,1); // prints 0.12 (note the shift in number of digits leave the stray 2

I'm printing a whole column of numbers and want the decimals to line up--hence remembering the old value and writing over it is not an option.

My doubles will never exceed 999 and never be negative. For example

Number result (decimals should line up but may not on this HTML page) 122.2 122.2 97.6 97.6 0.1 0.1 0 0.0

I’ve messed with sprintf but can’t figure out how to force 3 decimals but have 0 in the first if needed.

I can't be the only one who has ever done this, any suggestions?

You can specify width for sprintf, e.g. %3d or %03d

By default sprintf does not support floating point. It is possible to enable that support, at a substantial cost in memory.

Better to use dtostrf() to create strings, or avoid using the float/double data type.

Better to use dtostrf() to create strings, or avoid using the float/double data type.

Then, you can use sprintf() to put the dtostrf() string in another string the way you want - left justified, right-justified, etc.

Of course, there are lighter-weight functions that can achieve the same result, but they require brain power to use.

sprintf returns the number of chars, so you can pad with space characters upto your field’s size
dtostrf doesn’t, you’d have to call strlen() on the result.

  count = sprintf (buf, .....) ;
  lcd.write (buf) ;
  for (byte i = count ; i < len ; ) // where len is the length of the field you want to fill.
    lcd.write (' ') ;
// or
  s = dtostrf (buf, .....) ;
  count = strlen (s) ;
  lcd.write (s) ;
  for (byte i = count ; i < len ; )
    lcd.write (' ') ;

If the lcd library has a way to report the current character position you can simply interrogate it
of course…

Another way is to write the field with blanks first (this can flicker though):

  for (byte i = 0 ; i < len ; i++)
    lcd.write (' ') ;
  lcd.write (dtostrf (buf, .....))

Hi Kris,

You said "My doubles will never exceed 999 and never be negative", and gave some example data:

     Number       result
    122.2         122.2
    97.6           97.6
    0.1             0.1
    0               0.0

If you multiply each floating point number by 10, your data will fit into an int type - call it datum (or whatever), which sprintf's correctly. Use /10 for the integer part and %10 for the fraction part, with a dot in between, in your sprintf format: "%03d.%1d", (datum /10), (datum %10).

ChrisTenone, very interesting idea, i'll give that a shot.

ChrisTenone, it's padded with zero's

sprintf(str, "%03d.%1d", (tempdata / 10), (tempdata % 10));

gives this

000.0 007.4 014.8 022.2 029.6 037.0 044.4 051.8 059.2 066.6 074.0 081.4 088.8 096.2 103.6 111.0 118.4

Trying other methods cited above.

KrisKasprzak: ChrisTenone, it's padded with zero's

sprintf(str, "%03d.%1d", (tempdata / 10), (tempdata % 10));

gives this

000.0 007.4 014.8 022.2 029.6 037.0 044.4 051.8 059.2 066.6 074.0 081.4 088.8 096.2 103.6 111.0 118.4

Trying other methods cited above.

Whoops. I'm pretty new at using sprintf, so I usually need to work on it iteratively until I get the format right - I have a hard time imagining the result based on the format string. I didn't think it through all the way last night.

Use "%3d.%1d" (without the 0 between % and 3.) If you pass a value of zero to "%3d", it should print a single zero.

I DO think integers is the way to go. The range of your data fits it perfectly, and integer math is GOBS faster (and usually smaller) than floating point. Even complex functions can be optimized, and I'm guessing your program does some math.

ps, you can manually pad with spaces: If integerPart < 100 print a space, if integerPart < 10 print another space.

The %3d specifier says to print an int using at least 3 characters (" 1", " 30", "100", "1023"). If you use %03d, that says to print an int using at least three characters, and fill the field with leading zeros if needed ("001", "030", "100", "1023"). You can use any character between the % and the field width number for the pad character. %#4d would give "###1", "##30", "#100" and "1023" for the same values in the other examples.

Keeping a graphic LCD 'clean' if the library provides only basic primitives can be awkward. One simple ( but admittedly slow) way to erase obsolete text from the display is to re-write the text with foreground color specified the same as background color.

PaulS: The %3d specifier says to print an int using at least 3 characters (" 1", " 30", "100", "1023"). If you use %03d, that says to print an int using at least three characters, and fill the field with leading zeros if needed ("001", "030", "100", "1023"). You can use any character between the % and the field width number for the pad character. %#4d would give "###1", "##30", "#100" and "1023" for the same values in the other examples.

So then "% 3d.%1d" should do it, and fill with spaces.

So then "% 3d.%1d" should do it, and fill with spaces.

Since the space is the default fill character, %3d.%1d will do it.