String Comparison

So I am trying to create a function to update the status text on my LCD, and store the current value it has written so it only updates on a change of the status, but for some reason "currentstatus" is always blank... here is the code.

char status[40];
char currentstatus[40];

        /* Update the Status on the LCD */
        char* status = "Hello...";
          
          Serial.println(status);
          Serial.println(currentstatus);
        
          if(currentstatus != status) {
            updatestatus(status);
            char* currentstatus = status;
          }

Any ideas on where I am going wrong??

The value "status" will never equal "currentstatus" because both are separately defined arrays.

The name of the array is the same as the address of the array's first element. The name of the array is essentially used like a pointer to that first element. The addresses don't move when the contents of the arrays change. You're comparing the addresses.

If you want to see if the contents are identical to their first zero character (the terminator), see the strcmp( ) routine.

if (0 == strcmp(status, currentstatus)) { ... }

Anyone who wants to learn how pointers work should consider this assignment for homework: implement strlen(), strcpy(), strcmp(), strcat() and strchr(). The basic implementations are all extremely easy and compact and elegant, almost as elegant as V = R I.

It's best to make an annotation of what is going on here:

char status[40]; // create a global buffer named status
char currentstatus[40]; // create a global buffer named currentstatus

        /* Update the Status on the LCD */
        char* status = "Hello..."; // create a new pointer variable named status; point it to the word "Hello..."
        // note that the new status is completely unrelated to the buffer of the same name
          
          Serial.println(status); // print the thing pointed to by the pointer... prints "Hello..."
          Serial.println(currentstatus); // prints the contents of the currentstatus buffer (empty)
        
          if(currentstatus != status) { // This will always be true because status never points to currentstatus buffer
            updatestatus(status); // I don't know what this does
            char* currentstatus = status; // create a new pointer variable named currentstatus
            // note that this has nothing to do with the buffer above; make it point to the same "Hello" buffer
            // that the new "status" variable does
          } // the new currentstatus variable goes out of scope and is lost

I'll help you rewrite this if you want. Can you post the code for updatestatus in the meanwhile?

Thanks,

Mikal

Anyone who wants to learn how pointers work should consider this assignment for homework: implement strlen(), strcpy(), strcmp(), strcat() and strchr(). The basic implementations are all extremely easy and compact and elegant

Hi halley, I would argue that there is nothing about string handling in C that is elegant :wink: But as you say, the basic implementation is easy once you know how, although it's a little more difficult to ensure that buffers are never overrun.

although it's a little more difficult to ensure that buffers are never overrun

From the function's scope, it's not just difficult, there's no way to ensure that buffers aren't overrun. That's the major flaw with them: someone went all Dijkstra one day and wrote the string functions from a "math is pure and lovely" point of view, when they should have gone all Murphy instead from a "blowenfusen und poppencorken mit spitzensparken" point of view, and not trust the caller at all.

From the function's scope, it's not just difficult, there's no way to ensure that buffers aren't overrun.

Not sure I understand what you are saying. You can avoid buffer overruns in C, but it takes a lot of due care and attention on the part of the programmer. And using functions like strncpy does give better control over what is happening than strcpy

I hope we are not straying off the main topic of interest for the OP :wink:

halley, thanks for the function advice. I have never used C before (used to PHP) but the knowing I can use the standard string functions made a huge difference. Plus I was also able to add code to center the text (the LCD is 20 wide)...

  // Main Program
  char status[20];  // create buffer: status
  char currentstatus[20];  // create buffer: currentstatus

        /* Update the Status on the LCD */
        char* status = "Hello World.";
        updatestatus(status);
/*
  updatestatus(char* status)
  
  This function checks to see if the status passed is the currently 
  registered status.  If it is not it sets it to the currently 
  registered status, evaluates the length, computes the number of spaces
  to add to the front of the status to center it, and finally prints
  the formatted status to the top line of the LCD.
*/

void updatestatus(char* status) { 
  // Check and see if the currently display status is the active status
  if(0 != strcmp(currentstatus, status)) {
    
    strcpy(currentstatus,status);  // copy status to currentstatus to show it has been read.

    int statuslen = strlen(status);  // get the length of the status string
    int spaces = ((20 - statuslen) / 2);  // calculate the number of spaces to place in front to center the text on the LCD
    
    char statusf[20];  // create a buffer for formatted status: statusf
    char* space = " ";  // create a space
    for(int i=0; i<spaces; i++) {  // for each space that needs to be generated
      strcat(statusf,space);  // add space to the formatted status using strcat()
    }
    strcat(statusf,status);  // add the status message to the formatted status with leading spaces

    // Update the LCD top line
    lcd.print("?a");  // set the cursor to home
    lcd.print("?l");  // clear the line
    lcd.print(statusf);  // print the formatted status
  }
}

Thanks alot for your help. I am still very new to this, but you are all very helpful. This starts to get easy very quickly. I think is my lack of C knowledge holding me back.

Ryan--

Wow! That's a great improvement in only a few hours! Nice! Just a couple of comments: By declaring

char *status = "Hello World.";

you are redefining the name "status" in your function, effectively disabling access to the original one -- the buffer. It's best to avoid this kind of programming practice generally. In your case, you can avoid this by just directly calling

updatestatus("Hello World.");

without the intermediate variable declaration. (I realize that this is just test code, but the point is still valid.) Similarly, you don't need a variable called "space". It's exactly the same, more space efficient, and, I think, more readable to simply write

for (int i=0; i<spaces; i++ {
  strcat(statusf, " ");
}

Nice work.

Mikal

Thanks, I can usually pick this stuff up fairly quick.

I see what you mean about the declaration... I will most likely use updatestatus() in some other sub functions and call it directly.

I forgot you can just use " ", in strcat. Its things like that that will help me keep program size down.

Thanks for your help.

Anyone who wants to learn how pointers work should consider this assignment for homework: implement strlen(), strcpy(), strcmp(), strcat() and strchr(). The basic implementations are all extremely easy and compact and elegant, almost as elegant as V = R I.

I just finished an assignment involving implementing these in SPARC Assembly, they were elegant as far as that goes.