sprintf() and LCD question

I was looking for the best way to update LCD display. One 'tip' I found was to use sprintf().

After a lot of fiddling I, once again, had to come here.

I was following some examples and it's just not working. I must be doing something wrong but I have no clue what.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C  lcd(0x3F, 2, 1, 0, 4, 5, 6, 7);


void setup() {
  Serial.begin(9600);
  lcd.begin (16, 2);
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home();
}

void loop() {
  char msg[16] = "";
  int setting2 = 111;
  lcd.setCursor (0, 1); lcd.print(sprintf(msg, "Temperature: %03d", setting2));
}

I was under the impression that my outcome would be:

Temperature: 111

But it' not. The result is 16.

The msg[] should be the width of the message (per example), the %03d is a width of 3 and trailing 0's if the width is less than 3. The 'd' is integer value of setting2.

I don't know where the 16 comes from (it's not the value of msg[]).

:confused:

sprintf(msg, "Temperature: %03d", setting2);
lcd.print(msg);

sprintf return value: If successful, the total number of characters written is returned excluding the null-character appended at the end of the string, otherwise a negative number is returned in case of failure.

Read e.g. sprintf(3): formatted output conversion - Linux man page and check what it returns.

By the way, your buffer is one byte too small; you need to have space for the terminating nul-character.

Thank you both!

I was so busy with the formatting that I completely missed that I was outputting everything BUT the buffer.

I was using this for reference.

Now it works... man I made a dumb mistake, sorry!

void loop() {
  char msg[17];
  int setting2 = 111;
  sprintf(msg, "Temperature: %03d", setting2);
  lcd.setCursor (0, 1); lcd.print(msg);
}

Your code will break when setting2 is more than 3 digits (which would include the sign) as the buffer again isn't big enough.

You can test the value before calling sprintf.
2)
You can also look at snprintf. Make sure that the last byte of the buffer contains a '\0'.

Thanks Sterretje

I have a constrain on setting2 so it should never be larger than 3 digits. As for the '\O'... Do I need to reserve a position for it or is it something I should add?

The reference says:

Some programs imprudently rely on code such as the following
sprintf(buf, "%s some further text", buf);

Can you please show an example of how to use the \O?

I am going to look at snprintf now :slight_smile:

Thanks!

As for the '\O'... Do I need to reserve a position for it

Absolutely.

or is it something I should add?

Any string function will automatically add the NULL terminator. If you are directly adding to a string (char array), you should put the NULL terminator in the next position in the array whenever you add a character.

Can you please show an example of how to use the \O?

Sure, if you explain how you want to use the NULL.

snewpers:
Can you please show an example of how to use the \O?

You're supposed to use a zero, not a letter O.

sprintf() is a very powerful function, but most programs only use a very small portion of that power. In the code below, commenting out the str*() functions and using just sprintf() yields a flash size of 3302 bytes:

void loop() {
  char msg[18];
  char temp[5];
  int setting2 = 111;
  
  strcpy(msg, "Temperature: ");
  strcat(msg, itoa(setting2, temp, DEC));
//  sprintf(msg, "Temperature: %03d", setting2);
  Serial.println(msg);
}

The string version without calling sprintf() above uses only 2000 bytes of flash. In some cases, saving 1300 bytes of code space may be important.