char array problems

Hi all,

I have strange (set of) bug(s) which I believe may be due to a misunderstanding of how char arrays work.

In the following code snippet

void printOperatingDisplay(byte displayIdx)
{
  char degChar = 0b11011111; // degree symbol
  char intbuf[2];
  
  // non-working placement for the call
  // inttostr(intbuf, displayIdx + 1);

  char machineState[8];
  getState(machineState);
  int len = 4+tempRes+1; // 3 digits + decimal point + decimal places +1 for Null char termination 
  char currentTemp[len]; 
  if (0.0 < p.input < 1000.0)
  {
    dtostrf(p.input, len, tempRes+1, currentTemp);
    currentTemp[len-1]=0;
  }
  else
  {
    strcpy(currentTemp, "error");
  }
  lcd.setCursor(0, 0);
  
  // working placement for this call
  inttostr(intbuf, displayIdx + 1);
  
  fmt(strbuf, 3, intbuf, " ", machineState);
  rpad(strbuf, strbuf);
  lcd.print(strbuf);
  // lcd.setCursor(LCD_COLS-sizeof(currentTemp)-3, 0);
  lcd.setCursor(LCD_COLS-len-1,0);
  // fmt(strbuf, 3, "Temp: ", currentTemp, " C");
  lcd.print(currentTemp);
  // lcd.print((float)p.input, tempRes);
  lcd.print(degChar);
  lcd.print("C ");

If I call the function inttostr at the top of the function, the code doesn’t work as expected.
My output line on the 16x2 lcd is:

" state xx.x°C"

If I call it at after the setCursor line I get:

"1 state xx.x°C"
but ONLY if I add an extra decimal place and replace it with the Null char at the end of the array inside the if statement.

If I change the if statement to a single line:

dtostrf(p.input, len, tempRes, currentTemp);

I get the following output:

"1 state xx.x1°C" ← note the second copy of the value of intbuf before the degree symbol.

The inttostr function (by others):

char *inttostr(char *dest, short integer)
{
  if (integer == 0)
  {
    strcpy(dest, "0");
  }
  else
  {
    byte sign = 0;
    
    if (integer < 0)
    {
      sign = 1;
      dest[0] = '-';
      integer = integer * -1;
    }

    byte idx = 0;

    if (integer > 9999) idx = 4;
    else if (integer > 999) idx = 3;
    else if (integer > 99) idx = 2;
    else if (integer > 9) idx = 1;
    else if (integer > 0) idx = 0;    

    idx += sign;
    dest[idx+1] = 0;
    
    for (; idx >=0 && integer !=0; integer /= 10, idx--)
    {
      dest[idx]=(integer % 10) + '0';
    }
  }
  return dest;
}

Full code attached. printOperatingDisplay is at line 458 of the main (LcdCDTimer… .ino) and the inttostr function is in LcdKeypad.cpp

Many thanks.

LcdCDTimerMeetsShowtime10.zip (21.5 KB)

char intbuf[2];Single integer string ?

It seems like a lot of machinations just to print to an LCD. Why not just use sprintf()?

AWOL:

 char intbuf[2];

Single integer string ?

Yes, indeed, though may at some point become double digits I suppose...
Current values are 0,1&2.

BulldogLowell:
It seems like a lot of machinations just to print to an LCD. Why not just use sprintf()?

Overly machinated? Possibly, though as the menu management code base I adopted provided a set of elegant-seeming functions for building the lcd line buffer (concatenation, copying and left and right padding) I thought that that was the best way to do it. These functions are also used elsewhere for formatting content for the lcd.
I will take a look at sprintf.

bidoowee:
Overly machinated? Possibly, though as the menu management code base I adopted provided a set of elegant-seeming functions for building the lcd line buffer (concatenation, copying and left and right padding) I thought that that was the best way to do it. These functions are also used elsewhere for formatting content for the lcd.
I will take a look at sprintf.

when it comes to LCD's sprintf() and its safer cousin snprintf() rock.

all your padding will be a breeze if you study the C Format Specifiers

Side note: also look at adopting the F Macro for your string constants.

I will look into both of your suggestions.
I'd still like to understand why I am getting this behavior however. Currently - this just seems like voodoo. :smiling_imp: