"I want to adapt it to blink any value from 1 to 16 characters"
From below: In no case does a non-existent or small field width cause truncation of a numeric field; if the result of a conversion is wider than the field width, the field is expanded to contain the conversion result.
You want to avoid using that as a "feature" unless you use strlen() on the resulting string to know how much to erase.
Or you could print with "%016d" and erase by printing 16 spaces with a loop.
The format string is composed of zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments. Each conversion specification is introduced by the % character. The arguments must properly correspond (after type promotion) with the conversion specifier. After the %, the following appear in sequence:
Zero or more of the following flags:
The value should be converted to an "alternate form". For c, d, i, s, and u conversions, this option has no effect. For o conversions, the precision of the number is increased to force the first character of the output string to a zero (except if a zero value is printed with an explicit precision of zero). For x and X conversions, a non-zero result has the string 0x' (or 0X' for X conversions) prepended to it.
0 (zero) Zero padding. For all conversions, the converted value is padded on the left with zeros rather than blanks. If a precision is given with a numeric conversion (d, i, o, u, i, x, and X), the 0 flag is ignored.
A negative field width flag; the converted value is to be left adjusted on the field boundary. The converted value is padded on the right with blanks, rather than on the left with blanks or zeros. A - overrides a 0 if both are given.
' ' (space) A blank should be left before a positive number produced by a signed conversion (d, or i).
A sign must always be placed before a number produced by a signed conversion. A + overrides a space if both are used.
An optional decimal digit string specifying a minimum field width. If the converted value has fewer characters than the field width, it will be padded with spaces on the left (or right, if the left-adjustment flag has been given) to fill out the field width.
An optional precision, in the form of a period . followed by an optional digit string. If the digit string is omitted, the precision is taken as zero. This gives the minimum number of digits to appear for d, i, o, u, x, and X conversions, or the maximum number of characters to be printed from a string for s conversions.
An optional l or h length modifier, that specifies that the argument for the d, i, o, u, x, or X conversion is a "long int" rather than int. The h is ignored, as "short int" is equivalent to int.
A character that specifies the type of conversion to be applied.
The conversion specifiers and their meanings are:
diouxX The int (or appropriate variant) argument is converted to signed decimal (d and i), unsigned octal (o), unsigned decimal (u), or unsigned hexadecimal (x and X) notation. The letters "abcdef" are used for x conversions; the letters "ABCDEF" are used for X conversions. The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it is padded on the left with zeros.
p The void * argument is taken as an unsigned integer, and converted similarly as a %#x command would do.
c The int argument is converted to an "unsigned char", and the resulting character is written.
s The "char *" argument is expected to be a pointer to an array of character type (pointer to a string). Characters from the array are written up to (but not including) a terminating NUL character; if a precision is specified, no more than the number specified are written. If a precision is given, no null character need be present; if the precision is not specified, or is greater than the size of the array, the array must contain a terminating NUL character.
% A % is written. No argument is converted. The complete conversion specification is "%%".
eE The double argument is rounded and converted in the format "[-]d.ddde±dd" where there is one digit before the decimal-point character and the number of digits after it is equal to the precision; if the precision is missing, it is taken as 6; if the precision is zero, no decimal-point character appears. An E conversion uses the letter 'E' (rather than 'e') to introduce the exponent. The exponent always contains two digits; if the value is zero, the exponent is 00.
fF The double argument is rounded and converted to decimal notation in the format "[-]ddd.ddd", where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimal-point character appears. If a decimal point appears, at least one digit appears before it.
gG The double argument is converted in style f or e (or F or E for G conversions). The precision specifies the number of significant digits. If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1. Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision. Trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.
S Similar to the s format, except the pointer is expected to point to a program-memory (ROM) string instead of a RAM string.
In no case does a non-existent or small field width cause truncation of a numeric field; if the result of a conversion is wider than the field width, the field is expanded to contain the conversion result.
I spent a month with a bookmark in a reference before I knew half of that.
I hardly ever used it, I know I'd need to refer to it to be sure I got the bits right but I'm literate enough to read the reference.
Getting decimal digits from binary integers requires a lot of remainders and dividing with as many steps as the value has digits, but there are fast routines for that in the Arduino Playground,
I actually had not explored the playground, I end up there quite often in search results and see the big warning that it is now read only so I have never really looked there properly. Will explore now. I must say the Arduino site is not easy to search for stuff and a lot of things I am looking for refer to posts back from 2014 and some approaches have changed since then. And then of course there is very harsh comments to wade through as well.
I didn't get a lot of time today but I I think I am incrementally further along. From your comment strlen() I worked out that if can use itoa() and the strlen() to work out how many characters to blink. I did run into the issue however that the value being past may not be the full length of a max value to blink.
eg if I am;
editing hours it is 2 digits and pad by 0 if it is 1 digit, ie 5 = 05 or 15 = 15
editing minutes the spa can be used it could be 3 digits, and for arguments sake, 5 = 005 or 180 = 180
editing the LDR sensitivity can be 4 digits 1024 to 0, ie 1 = 0001 to 1024
So I adapted a post to use a for loop to add the 0's in. I did try and manipulate the %02d so it could be %0(mymaxval)d but that did not work.
The code below seems to work but not tested to destruction yet. So thank you for your help, your one key work has lead me to learn all about itoa(), strlen() and i understand sprintf a little more.
void flashValue(int val, int maxval, byte column, byte line)
{
static unsigned long lastTime = 0; // Static variables preserves data between function calls.
static bool flashOn = false;
char st_val[12]; // int with max length with plus/minus and terminator
char st_maxval[12]; //holds the maximum value the passed int can be
itoa(val, st_val, 10);
itoa(maxval, st_maxval, 10);
byte vallen = strlen(st_val); // gets the length of the current value
byte maxvallen = strlen(st_maxval); // gets the length of the maximum value
if (millis() - lastTime > 500UL)
{
if (flashOn)
{
lcd.setCursor(column, line);
if(maxvallen > vallen) // check if the value is less characters than the max value
{
for(byte i = 0; i < (maxvallen - vallen); i++)
lcd.print("0"); // for loop to add in required 0 for padding
}
lcd.print (val); // print the val after the 0's
}
else
{
lcd.setCursor (column, line);
for(byte i = 0; i < strlen(st_maxval); i++)
{
lcd.print(" "); // replace the max length with blank spaces for the blink
}
}
flashOn = !flashOn;
lastTime = millis(); // rest the timer
}
}
If the mStates are all power of 2, each could be a bit. I see 8, a byte would suffice.
Value of mState if a state is on:
m_Economy = 1, m_StandBy = 2, m_InUse = 4, m_ExitDelay = 8,
m_Settings = 16, m_SelComfortTimes = 32, m_SelTemps = 64, m_SelDelays = 128
You can use an enum to make the names code the numbers.
Now suppose mState will be one of those values and I want to see if it's more or less than 10?
Selection by mask: if ( mState & ( m_StandBy | m_InUse | m_ExitDelay ) > 0 ) lets you see what bits are masked ON.
This is the mask: ( m_StandBy | m_InUse | m_ExitDelay ) ...........it only has bits for 3 states set.
if ( mState & the mask only lets those bits set 1 in the mask through, only 0,2,4, or 8 can result.
1 | 2 == 3
3 & 2 == 2, the & 2 masked off the 1 of the 3.
You can stack bits for different states into an 8 or 16 bit unsigned then use &, |, ^ to mask out combinations very fast.