Using stored value from EEPROM

Hi all,

Here's something I thought should have been the simplest thing ever! But I'm completely baffled instead!

Here's a code snip of what I'm doing. I've simplified it for the purpose of this post... I'm retrieving an already stored value from EEPROM, then doing a compare with the string which was actually stored. But the 2 strings don't evaluate as the same.

I've entered some debug Serial.Println commands to test it out. The first one which just outputs the value I retrieved from EEPROM prints the correct and expected string. I've manually copied it to a notepad and compared to verify this. But none of the below if statements evaluate to True. I've resorted to all the different variations of comparing just in case I've grossly misunderstood it, but they're all false.

What am I doing wrong?

    struct { 
      uint val = 0;
      char str[33] = "";
    } myAppKey;
    uint addr = 0;

    myAppKey.val = 0; 
    //Get the value from eeprom
    EEPROM.get(addr, myAppKey);
    Serial.println("App Key Value from EEPROM::" + String(myAppKey.str) + "::");

    if (String(myAppKey.val) == "abcdefghijklmnopqrtsuvwxyz123456")
      Serial.println("App Key Matches");
    if (String(myAppKey.val) == String("abcdefghijklmnopqrtsuvwxyz123456"))
      Serial.println("App Key Matches String");
    if (String(myAppKey.val).c_str() == String("abcdefghijklmnopqrtsuvwxyz123456").c_str())
      Serial.println("App Key Matches as Converted to c_str");

    const char* myAppKeyChar = String(myAppKey.val).c_str();
    //... Do other stuff...

Please post a complete program that save the value to the EEPROM, reads it back in to a variable and then does a comparison between the variable and a value coded into the program

Tell us which board you use, I assume it is not an Arduino board.

Read the reference of strncpy: strncpy - C++ Reference.
That function does not magically append a zero-terminator. You always have to think of the zero-terminator when counting the exact size for a string.

The strncpy() function was created a long time ago, and the padding with zero's was needed then. Today it is used to prevent buffer overflow. That is not what that function was created for.
You might consider to start using strlcpy(). However, when you start using strlcpy() en strlcat() then you have to know what those function do, or you can still get into trouble.

When converting the 'uint val' to a String, it is probably a number. It is never "abcdefghijklmnopqrtsuvwxyz123456".

When converting the 'uint val' to a String, it is probably a number. It is never "abcdefghijklmnopqrtsuvwxyz123456".

Thanks for the response guys. The board is a NodeMCU - Wemos D1 mini.

I'll research the zero-terminator issue. I'm from a C# .Net background where the road is already paved most of the time.

Here's the code that saves the values. I'm definitely saving the string "abcdefghijklmnopqrtsuvwxyz123456" and when reading back, I'm getting the same string.

    struct { //value to store into EEPROM
	  uint val = 0;
	  char str[33] = "";
	} myAppKey;
	uint addr = 0; //Start point of my value

    //Save the string into EEPROM
    // first clear 'myAppKey' structure
    myAppKey.val = 0; 
    // Now save the new value
strncpy("abcdefghijklmnopqrtsuvwxyz123456", 33);

Where are you copying the string to ?


strncpy("abcdefghijklmnopqrtsuvwxyz123456", 33);

Where are you copying the string to ?

OMG! Oops. My bad. I tried to get rid of all the other unrelated logic to focus on the problem and ended up messing up the code. Then in the process of pointing out what the correct code was, I discovered that I was copying into str:

    strncpy(myAppKey.str, "abcdefghijklmnopqrtsuvwxyz123456",33);

But reading from val

const char* myAppKeyChar = String(myAppKey.val).c_str();

Changing it to this solved the problem:

const char* myAppKeyChar = String(myAppKey.str).c_str();

Goes to show the value of posting the whole code, even though you think it's not relevant. Thankyou!!!

I’m glad that you got it working but do you really need to use Strings and do nasty type conversions like this ?

const char* myAppKeyChar = String(myAppKey.str).c_str();

I'm from a C# .Net background

That explains it.

The Arduino "String" is a class that can do a lot and works with other Arduino functions. I think it was developed for Arduino. It is not recommended for an Arduino Uno because a fragmented heap might cause problems. For a ESP8266 you don't have to worry about that.

You can always use the old 'c' functions: strcpy, strlen, strcat, sprintf, scanf, and so on. You always have to think about the zero-terminator. Always. I often use a single global buffer for temporary conversions. For example char buffer[80].
The sprintf and scanf are not 100% straightforward because a "%d" is a 16 bit integer for the Arduino Uno and a 32 bit integer for the ESP8266.

The 'C++' language has additions which are rarely used with Arduino. There is for example the std:string object. It is a standard, so you can use it if you want.

You can use the Arduino String object if it makes the code easier to read.
When you are only dealing with character arrays, and you are constantly converted it between a String and character array, then it might be easier to use only character arrays.