Thanks @UKHeliBob
If you are ignoring method error returns (and lots of coders ignore error returns) than not much difference between strncpy and strlcpy,
The advantage strlcpy/strlcat have is that you can easily check for truncation errors. That option is missing from strncpy/strncat and that is the first reason I consider strlcpy/strlcat is the better choice.
The second reason is that coders tend to use strncpy/strncat as a pair and then get the strncat method args wrong. They don't do the correct calculation as you have done. strlcat is a simpler choice as it does the calc for you internally.
Here is the strlcpy strlcat version with error checking
char dest[10]; //space for 9 characters plus a terminating '\0'
void setup()
{
Serial.begin(115200);
for (int i = 10; i > 0; i--) {
delay(500);
Serial.print(i); Serial.print(' ');
}
Serial.println("Uno started ");
if (strlcpy(dest, "12345", sizeof(dest)) >= sizeof(dest)) { //should be plenty of room for these characters
Serial.println(F("Error dest too small"));
} else {
Serial.println(dest);
}
//
if (strlcpy(dest, "123456789", sizeof(dest)) >= sizeof(dest)) { //should be just enough room for these characters
Serial.println(F("Error dest too small"));
} else {
Serial.println(dest);
}
//
if (strlcpy(dest, "1234567890ABCDEF", sizeof(dest)) >= sizeof(dest)) { //far too many characters to fit
Serial.println(F("Error dest too small"));
} else {
Serial.println(dest);
}
//
if (strlcpy(dest, "X", sizeof(dest)) >= sizeof(dest)) { //start with an X in the destination
Serial.println(F("Error dest too small"));
}
if (strlcat(dest, "12345", sizeof(dest)) >= sizeof(dest)) { //plenty of room to add these characters
Serial.println(F("Error dest too small"));
} else {
Serial.println(dest);
}
//
if (strlcpy(dest, "X", sizeof(dest)) >= sizeof(dest)) { //start with an X in the destination
Serial.println(F("Error dest too small"));
}
if (strlcat(dest, "12345678", sizeof(dest)) >= sizeof(dest)) { //enough room for these characters
Serial.println(F("Error dest too small"));
} else {
Serial.println(dest);
}
//
if (strlcpy(dest, "X", sizeof(dest)) >= sizeof(dest)) { //start with an X in the destination
Serial.println(F("Error dest too small"));
}
if (strlcat(dest, "1234567890", sizeof(dest)) >= sizeof(dest)) { //too many characters to fit in destination
Serial.println(F("Error dest too small"));
} else {
Serial.println(dest);
}
}
void loop()
{
}
Your output is (the same as strlcpy/ strlcat without error checking)
12345
123456789
123456789
X12345
X12345678
X12345678
The strlcpy/strlcat output with error checking is
12345
123456789
Error dest too small
X12345
X12345678
Error dest too small
Personally I prefer SafeString, I find the code simpler and the error msgs much better.
#include "SafeString.h"
char dest[10]; //space for 9 characters plus a terminating '\0'
void setup()
{
Serial.begin(115200);
for (int i = 10; i > 0; i--) {
delay(500);
Serial.print(i); Serial.print(' ');
}
Serial.println("Uno started ");
SafeString::setOutput(Serial);
cSFA(sfDest,dest); // wrap in a safe string
sfDest = "12345"; //should be plenty of room for these characters
Serial.println(dest);
//
sfDest = "123456789"; //should be just enough room for these characters
Serial.println(dest);
//
sfDest = "1234567890ABCDEF"; //far too many characters to fit
Serial.println(dest);
//
sfDest = "X"; //start with an X in the destination
sfDest += "12345"; //plenty of room to add these characters
Serial.println(dest);
//
sfDest = "X"; //start with an X in the destination
sfDest += "12345678"; //enough room for these characters
Serial.println(dest);
//
sfDest = "X"; //start with an X in the destination
sfDest += "1234567890"; //too many characters to fit in destination
Serial.println(dest);
}
void loop()
{
}
The output is
12345
123456789
Error: sfDest = "1234567890ABCDEF"
needs capacity of 16
sfDest cap:9 len:9 '123456789'
X12345
X12345678
Error: sfDest.concat() needs capacity of 11(i.e. char[12]) for the first 10 chars of the input.
Input arg was '1234567890'
sfDest cap:9 len:1 'X'
X