sprintf_P formating questions.

Hi,

I've been trying to get my head around various different formating options for sprintf_P. The following code....

  const prog_char TEST_03[] PROGMEM = "char<%c>,integer<%d>,integer<%d>,unsigned integer<%u>,unsigned integer<%u>, byte<%d>,byte<%d>,long<%ld>,long<%ld>,unsigned long<%lu>,unsigned long<%lu>.";
  
  char testChar='a';
  int testIntMin = -32768;
  int testIntMax = 32767;
  unsigned int testUnIntMin = 0;
  unsigned int testUnIntMax = 65535;
  byte testByteMin = 0;
  byte testByteMax = 255;
  long testLongMin = -2147483648L ;
  long testLongMax = 2147483647L;
  unsigned long testUnLongMin = 0UL;
  unsigned long testUnLongMax = 4294967295UL;
  char info[300];
  sprintf_P(info,TEST_03,testChar,testIntMin,testIntMax,testUnIntMin,testUnIntMax,testByteMin,testByteMax,testLongMin,testLongMax,testUnLongMin,testUnLongMax);
  Serial.println(info);

Produces what appears to be the correct result...

char<a>,integer<-32768>,integer<32767>,unsigned integer<0>,unsigned integer<65535>, byte<0>,byte<255>,long<-2147483648>,long<2147483647>,unsigned long<0>,unsigned long<4294967295>.

However, having fiddled with this for ages, it's apparent that there can be big difference between getting it to work with a particular value, and getting it to work with all values.

Can someone please confirm that that the formatting options I've used should work with all possible values of the variables I'm using?

Cheers

I can't see anything wrong with it.
What is the problem ?

BigusDickus:
it's apparent that there can be big difference between getting it to work with a particular value, and getting it to work with all values.

If you've found a value that doesn't seem to be being handled correctly, show us an example and tell us what you expected it to do and what it actually does, and perhaps we can see what the problem is.

What is the problem ?

There isn't actually a problem with the example I've given, what I'm saying is that some formatting options appear to work (i.e. compile ok, and display a value) but don't actually display the correct value. I was just looking for confirmation that I should be using the following display options...
%c = character
%d = integer, byte
%u = unsigned integer
%ld = long
%lu = unsigned long
There are lots of google pages on sprintf, but the exact options seems to vary from one flavour of C to the next.

Thanks

There are more, X, x, s. Even the string has formatting options.
Only the float and double float are not included by default in the Arduino.

It took some time for me to find a reference, but it turned out to be on the Arduino site.
This is explanation, Arduino Playground - Printf
That page has a link to the man page with the full specification, sprintf(3): formatted output conversion - Linux man page

There is no ambiguity.

The basic printf formatting options are standard and the same on all versions of C I have ever seen. Some advanced options are slightly different, but the base set is always the same. printf has evolved over time, but any differences talked about are in historical versions of C or on very esoteric systems with strange word sizes. All current versions of C provide the same facilities, but some also provide backwards compatibility with old systems.

The only caveat is that some use %i instead of %d, but these days pretty much all the versions of C I have worked with implement both, and they both do the same.

In general the format of options is %[options]Z, where [options] is a set of formatting options and Z is the formatting character. There are other options, but you don't need to know that right now, except maybe the "l" prefix to the formatting character to signify "long".

%c is a single signed byte from -128 to 127, represented as an ASCII character
%d or %i is a signed integer - on the Arduino an integer is two bytes - from -32768 to 32767 represented as numbers.
%ld is a signed long - on the Arduino it's 4 bytes - from ?2,147,483,648 to 2,147,483,647 represented as numbers.
%u is an unsigned integer from 0 to 65535 represented as numbers.
%lu is an unsigned long from 0 to 4,294,967,295
%s is a null-terminated string (character array)
%x is a lower-case hexadecimal representation of the value - the precision is provided as a prefix numeric value. This can be used for any numeric data
%X is an upper-case hexadecimal representation of the value - the precision is provided as a prefix numeric value. This can be used for any numeric data
%f would be a floating point value but isn't supported for code size reasons.

Examples:

65 => "%c" => "A"
12345 => "%d" => "12345"
17 => "%03d" => "017"
23456 => "%04X" => "5BA0"
"purple" => "barney is %s" => "barney is purple"

However, having fiddled with this for ages, it's apparent that there can be big difference between getting it to work with a particular value, and getting it to work with all values.

I still don't understand what you mean by this.

Have you found an actual example that doesn't work properly ?

It is more likely to be the case, that you are trying to print the value of a pointer ( instead of the value that the pointer points to ), than getting an error with some particular value.