I have been working on making a counter that displays the string "Total: " and has a left justified number, and similarly, this is displayed on the second line of the LCD. When trying to debug the program I can display each individual line on the display by themselves, but never on the screen simultaneously.
I believe I narrowed the problem down to the update function and how I make the String to display. This is because I can test other code with defined strings, not dynamic strings, that I know works and displays two lines.
I did set up the LCD as a 16x2 at the beginning of startup.
//Useful information to remove confusion
static char countText[] = "Total: "; // 7 chars long
static char specialText[] = "Interview: "; //11 chars long
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
//String to display
char* text(char* initial, int num){
int i = 0;
//Make a left aligned count
char actualArray[17];
char* printText = actualArray;
char count[9];
itoa(num, count, 10);
char spaces[16];
int countLength = strlen(count);
strcat(printText, initial);
for(i = strlen(printText); i < (16-countLength); i++)
strcat(spaces, " ");
strcat(printText, spaces);
strcat(printText, count);
strcat(printText, "\0"); //Close the string and ignore if there is text here
return printText;
}
//Function that is called everytime the count is updated
int UpdateScreen(){
lcd.clear();
// delay(50); //Debug
lcd.setCursor(0,0); //Start at character 0 on line 0
lcd.print(text(countText, cCount));
// delay(50); //Debug
lcd.setCursor(0,1);
lcd.print(text(specialText, cRCount));
return 0;
}
Ok, spaces is declared to be 16 bytes long, but it needs 17 - one extra for the nul terminator. And there's really no need to use strcat to fill it with spaces - horribly inefficient.
"Interview: " - 11 chars
spaces - 16 chars
So you need 27 chars, plus one for the nul terminator. actualArray is defined to have a length of 17.
Furthermore, printText is a pointer to actualArray. actualArray is an "automatic" variable - it's defined on the stack and it disappears after the function is done. So you are returning a pointer to a chunk of memory that is about to be used by something else.
And furthermore to that, because actualArray is allocated from the stack, it contains garbage. This means that there is no guarrantee that the first byte will be a null terminator. So when you [nobbc]strcat(printText, initial);[/nobbc] , strcat will search through memory until it finds the first zero in memory, and append initial at that point. This could be anywhere and so will likely scribble over the top of something important.
to fix (without doing too much violence to the original code):
char* text(char* initial, int num) {
//Make a left aligned count
static char actualArray[28]; // maximum length of the string we are going to need (11+16), plus 1
char count[7]; // maxint is 16k, so 5 digits, a negative sign, and a null terminator is enough.
itoa(num, count, 10);
int countLength = strlen(count);
char spaces[17];
memset(spaces, ' ', 16); // fill with 16 spaces
spaces[16 - countLength] = '\0'; // terminate at appropriate spot
strcnpy(actualArray, initial, 11);
strcat(actualArray, spaces);
strcat(actualArray, count);
return actualArray;
}