user-1: I need to implement EEPROM Read & Write functionality to my project.
I've been learning how to use the EEPROM on the last few days, however I'm struggling to Read & Write Strings to EEPROM.
Debugging the Received Data:

Received Data: The data received is correct.
EEPROM Data: It seem it has data but I am receiving Garbage Characters.

After reading several answers, I seem to fail understanding the reason behind my failure.
Sure I could "Copy / Paste", probably make it work and not understand the cloned code, but I wouldn't learn anything from that.
Therefore posting another thread regarding this subject (not exactly duplicate) requesting some help and/or guidance; for the sake of understanding and solving my issue.
Code
int ADDR_USERNAME       = 2;           // Username Data Lenght Address on EEPROM.

/* Get Username from EEPROM */
String EE_ReadUsername()
{
  int dataLength  = EEPROM.read(ADDR_USERNAME);       // Get the Data Length from EEPROM Address Position.
  int dataAddress = ADDR_USERNAME + 1;                // Data Initial Address on EEPROM

  char data[dataLength];                              // Assign the Array Length

  for (int i = 0; i < dataLength; i++)                // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
  {
    char c = EEPROM.read(dataAddress + i);            // Add EEPROM Address Char to Array
  }

  // DEBUG START
  Serial.print("VALUE: ");
  Serial.println(String(data));
  // DEBUG END

  return String(data);                                // Return the Data.
}

/* Save Username to EEPROM */
void EE_WriteUsername(String str)
{
  byte len = str.length();                            // Get the String Length.
  int dataAddress = ADDR_USERNAME + 1;                // Set the Initial Data Address

  EEPROM.update(ADDR_USERNAME, len);                  // Store the String Length to EEPROM

  for (int i = 0; i < len; i++)                       // Iterate over each char in String.
  { 
    EEPROM.update(dataAddress + i, str[i]);           // Assign each char from Received String to an Address Position in EEPROM.
  }
}

Thanks in advance.

user7508: In EE_ReadUsername(), you wrote:
char c = EEPROM.read(dataAddress + i);

This variable (c) is set but never used. You may want to add that
character to the data character array.
Also, the array has to be terminated with a NUL byte.

user-1: Giving this thread some more value while taking into consideration @Edgar Bonet's help (the accepted answer for this thread); I'm answering my own question with my full header class code (more EEPROM features) for further reference for myself and other users, who might be learning.

Note(s):

The regions are there for a backup reference purpose.
Feel free to edit and improve the answer and improve comments with advanced and knowleadgeable information.
Null Terminating char is NOT added to the EEPROM.
The Null Terminating char '\n' or '\0' is added to the array when reading (only).
This prevents writing (unnecessary) addresses to EEPROM.


Code
#pragma region <Includes>
#include <EEPROM.h>
#pragma endregion


#pragma region <Configuration>

#define ADDR_BRIGHTNESS   0           // LCD Brightness Data Address on EEPROM.
#define ADDR_CONTRAST     1           // LCD Contrast Data Address on EEPROM. [NOT IMPLEMENTED]
#define ADDR_USERNAME     2           // Username Data Lenght Address on EEPROM.
#define ADDR_COMPUTERNAME 14          // Computer Data Length Initial Address on EEPROM.

#pragma endregion

#pragma region <CRC>
unsigned long EEPROM_CRC(void)
{
  const unsigned long crc_table[16] = 
  {
    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
  };

  unsigned long crc = ~0L;

  for (int index = 0 ; index < EEPROM.length()  ; ++index)
  {
    crc = crc_table[(crc ^ EEPROM[index]) & 0x0f] ^ (crc >> 4);
    crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4);
    crc = ~crc;
  }

  return crc;
}

/* Performs a Cyclic Redundancy Check and Prints a Report on Serial Monitor */
void EE_CRC()
{
  Serial.println(" *** Performing EEPROM Cyclic Redundancy Check...");
  Serial.print(" *** EEPROM Length: ");                                // Print Length of Data to run CRC on.
  Serial.println(EEPROM.length());

  Serial.print(" *** EEPROM CRC32 Data: 0x");                          // Print the Result of Calling EEPROM_CRC()
  Serial.println(EEPROM_CRC(), HEX);
}
#pragma endregion

/* Iterate Through Each byte of the EEPROM Storage and Set all of the bytes to 0. */
void EE_ERASE()
{
  Serial.println(" *** ERASING EEPROM MEMORY...");
  
  for (int i = 0; i < EEPROM.length(); i++) 
  { EEPROM.write(i, 0); }

  Serial.println(" *** EEPROM ERASED!");
}


#pragma region <User Name>
/* Get Username from EEPROM */
String EE_ReadUsername()
{
  int dataLength  = EEPROM.read(ADDR_USERNAME);         // Get the Data Length from EEPROM Address Position.
  int dataAddress = ADDR_USERNAME + 1;                  // Data Initial Address on EEPROM

  char data[dataLength +1];                             // Assign the Array Length (+1 to Add the Null Terminating Char).

  for (int i = 0; i < dataLength; i++)                  // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
  {
    data[i] = EEPROM.read(dataAddress + i);             // Add EEPROM Address Char to Array
  }

  data[dataLength] = '\0';                              // Terminate the char String (Add Null Terminating Char)

  return String(data);                                  // Return the Data.
}

/* Save Username to EEPROM */
void EE_WriteUsername(String str)
{
  byte len = str.length();                              // Get the String Length.
  int dataAddress = ADDR_USERNAME + 1;                  // Set the Initial Data Address

  EEPROM.update(ADDR_USERNAME, len);                    // Store the String Length to EEPROM

  for (int i = 0; i < len; i++)                         // Iterate over each char in String.
  { 
    EEPROM.update(dataAddress + i, str[i]);             // Assign each char from Received String to an Address Position in EEPROM.
  }
}
#pragma endregion


#pragma region <Computer Name>
/* Get Computer Name from EEPROM */
String EE_ReadComputername()
{
  int dataLength  = EEPROM.read(ADDR_COMPUTERNAME);     // Get the Data Length from EEPROM Address Position.
  int dataAddress = ADDR_COMPUTERNAME + 1;              // Data Initial Address on EEPROM

  char data[dataLength +1];                             // Assign the Array Length (+1 to Add the Null Terminating Char).

  for (int i = 0; i < dataLength; i++)                  // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
  {
    data[i] = EEPROM.read(dataAddress + i);             // Add EEPROM Address Char to Array
  }

  data[dataLength] = '\0';                              // Terminate the char String (Add Null Terminating Char)

  return String(data);                                  // Return the Data.
}

/* Save Computer Name to EEPROM */
void EE_WriteComputername(String str)
{
  byte len = str.length();                              // Get the String Length.
  int dataAddress = ADDR_COMPUTERNAME + 1;              // Set the Initial Data Address

  EEPROM.update(ADDR_COMPUTERNAME, len);                // Store the String Length to EEPROM
  
  for (int i = 0 ; i < len; i++)                        // Iterate over each char in String.
  {
    EEPROM.update(dataAddress + i, str[i]);             // Assign each char from Received String to an Address Position in EEPROM.
  }
}
#pragma endregion


#pragma region <Brightness>
int EE_ReadBrightness()
{
  return EEPROM.read(ADDR_BRIGHTNESS);
}

void EE_WriteBrightness(int val)
{  
  EEPROM.update(ADDR_BRIGHTNESS, val);
}
#pragma endregion


-1: <p>I need to implement EEPROM Read &amp; Write functionality to my project.<br/>
I've been learning how to use the EEPROM on the last few days, however I'm struggling to Read &amp; Write Strings to EEPROM.</p>
<p><strong>Debugging the Received Data:</strong></p>
<ul>
<li>Received Data: The data received is correct.</li>
<li>EEPROM Data: It seem it has data but I am receiving Garbage Characters.</li>
</ul>
<p>After reading several answers, I seem to fail understanding the reason behind my failure.<br/>
Sure I could &quot;Copy / Paste&quot;, probably make it work and not understand the cloned code, but I wouldn't learn anything from that.<br/>
Therefore posting another thread regarding this subject (not exactly duplicate) requesting some help and/or guidance; for the sake of understanding and solving my issue.</p>
<p><strong>Code</strong></p>
<pre><code>int ADDR_USERNAME       = 2;           // Username Data Lenght Address on EEPROM.

/* Get Username from EEPROM */
String EE_ReadUsername()
{
  int dataLength  = EEPROM.read(ADDR_USERNAME);       // Get the Data Length from EEPROM Address Position.
  int dataAddress = ADDR_USERNAME + 1;                // Data Initial Address on EEPROM

  char data[dataLength];                              // Assign the Array Length

  for (int i = 0; i &lt; dataLength; i++)                // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
  {
    char c = EEPROM.read(dataAddress + i);            // Add EEPROM Address Char to Array
  }

  // DEBUG START
  Serial.print(&quot;VALUE: &quot;);
  Serial.println(String(data));
  // DEBUG END

  return String(data);                                // Return the Data.
}

/* Save Username to EEPROM */
void EE_WriteUsername(String str)
{
  byte len = str.length();                            // Get the String Length.
  int dataAddress = ADDR_USERNAME + 1;                // Set the Initial Data Address

  EEPROM.update(ADDR_USERNAME, len);                  // Store the String Length to EEPROM

  for (int i = 0; i &lt; len; i++)                       // Iterate over each char in String.
  { 
    EEPROM.update(dataAddress + i, str[i]);           // Assign each char from Received String to an Address Position in EEPROM.
  }
}
</code></pre>
<p>Thanks in advance.</p>
 7508: <p>In <code>EE_ReadUsername()</code>, you wrote:</p>
<pre class="lang-cpp prettyprint-override"><code>char c = EEPROM.read(dataAddress + i);
</code></pre>
<p>This variable (<code>c</code>) is set but never used. You may want to add that
character to the <code>data</code> character array.</p>
<p>Also, the array has to be terminated with a NUL byte.</p>
 -1: <p>Giving this thread some more value while taking into consideration @Edgar Bonet's help (the accepted answer for this thread); I'm answering my own question with my full header class code (more EEPROM features) for further reference for myself and other users, who might be learning.</p>
<hr/>
<p><strong>Note(s):</strong></p>
<ol>
<li>The regions are there for a backup reference purpose.</li>
<li>Feel free to edit and improve the answer and improve comments with advanced and knowleadgeable information.</li>
<li>Null Terminating char is NOT added to the EEPROM.
The Null Terminating char '\n' or '\0' is added to the array when reading (only).
This prevents writing (unnecessary) addresses to EEPROM.</li>
</ol>
<hr/>
<p><strong>Code</strong></p>
<pre><code>#pragma region &lt;Includes&gt;
#include &lt;EEPROM.h&gt;
#pragma endregion


#pragma region &lt;Configuration&gt;

#define ADDR_BRIGHTNESS   0           // LCD Brightness Data Address on EEPROM.
#define ADDR_CONTRAST     1           // LCD Contrast Data Address on EEPROM. [NOT IMPLEMENTED]
#define ADDR_USERNAME     2           // Username Data Lenght Address on EEPROM.
#define ADDR_COMPUTERNAME 14          // Computer Data Length Initial Address on EEPROM.

#pragma endregion

#pragma region &lt;CRC&gt;
unsigned long EEPROM_CRC(void)
{
  const unsigned long crc_table[16] = 
  {
    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
  };

  unsigned long crc = ~0L;

  for (int index = 0 ; index &lt; EEPROM.length()  ; ++index)
  {
    crc = crc_table[(crc ^ EEPROM[index]) &amp; 0x0f] ^ (crc &gt;&gt; 4);
    crc = crc_table[(crc ^ (EEPROM[index] &gt;&gt; 4)) &amp; 0x0f] ^ (crc &gt;&gt; 4);
    crc = ~crc;
  }

  return crc;
}

/* Performs a Cyclic Redundancy Check and Prints a Report on Serial Monitor */
void EE_CRC()
{
  Serial.println(&quot; *** Performing EEPROM Cyclic Redundancy Check...&quot;);
  Serial.print(&quot; *** EEPROM Length: &quot;);                                // Print Length of Data to run CRC on.
  Serial.println(EEPROM.length());

  Serial.print(&quot; *** EEPROM CRC32 Data: 0x&quot;);                          // Print the Result of Calling EEPROM_CRC()
  Serial.println(EEPROM_CRC(), HEX);
}
#pragma endregion

/* Iterate Through Each byte of the EEPROM Storage and Set all of the bytes to 0. */
void EE_ERASE()
{
  Serial.println(&quot; *** ERASING EEPROM MEMORY...&quot;);
  
  for (int i = 0; i &lt; EEPROM.length(); i++) 
  { EEPROM.write(i, 0); }

  Serial.println(&quot; *** EEPROM ERASED!&quot;);
}


#pragma region &lt;User Name&gt;
/* Get Username from EEPROM */
String EE_ReadUsername()
{
  int dataLength  = EEPROM.read(ADDR_USERNAME);         // Get the Data Length from EEPROM Address Position.
  int dataAddress = ADDR_USERNAME + 1;                  // Data Initial Address on EEPROM

  char data[dataLength +1];                             // Assign the Array Length (+1 to Add the Null Terminating Char).

  for (int i = 0; i &lt; dataLength; i++)                  // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
  {
    data[i] = EEPROM.read(dataAddress + i);             // Add EEPROM Address Char to Array
  }

  data[dataLength] = '\0';                              // Terminate the char String (Add Null Terminating Char)

  return String(data);                                  // Return the Data.
}

/* Save Username to EEPROM */
void EE_WriteUsername(String str)
{
  byte len = str.length();                              // Get the String Length.
  int dataAddress = ADDR_USERNAME + 1;                  // Set the Initial Data Address

  EEPROM.update(ADDR_USERNAME, len);                    // Store the String Length to EEPROM

  for (int i = 0; i &lt; len; i++)                         // Iterate over each char in String.
  { 
    EEPROM.update(dataAddress + i, str[i]);             // Assign each char from Received String to an Address Position in EEPROM.
  }
}
#pragma endregion


#pragma region &lt;Computer Name&gt;
/* Get Computer Name from EEPROM */
String EE_ReadComputername()
{
  int dataLength  = EEPROM.read(ADDR_COMPUTERNAME);     // Get the Data Length from EEPROM Address Position.
  int dataAddress = ADDR_COMPUTERNAME + 1;              // Data Initial Address on EEPROM

  char data[dataLength +1];                             // Assign the Array Length (+1 to Add the Null Terminating Char).

  for (int i = 0; i &lt; dataLength; i++)                  // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
  {
    data[i] = EEPROM.read(dataAddress + i);             // Add EEPROM Address Char to Array
  }

  data[dataLength] = '\0';                              // Terminate the char String (Add Null Terminating Char)

  return String(data);                                  // Return the Data.
}

/* Save Computer Name to EEPROM */
void EE_WriteComputername(String str)
{
  byte len = str.length();                              // Get the String Length.
  int dataAddress = ADDR_COMPUTERNAME + 1;              // Set the Initial Data Address

  EEPROM.update(ADDR_COMPUTERNAME, len);                // Store the String Length to EEPROM
  
  for (int i = 0 ; i &lt; len; i++)                        // Iterate over each char in String.
  {
    EEPROM.update(dataAddress + i, str[i]);             // Assign each char from Received String to an Address Position in EEPROM.
  }
}
#pragma endregion


#pragma region &lt;Brightness&gt;
int EE_ReadBrightness()
{
  return EEPROM.read(ADDR_BRIGHTNESS);
}

void EE_WriteBrightness(int val)
{  
  EEPROM.update(ADDR_BRIGHTNESS, val);
}
#pragma endregion
</code></pre>
