1

I made a sketch like this:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  char str1[64] = "test with spaces";
  char str2[32] = "test with spaces";

  Serial.println(str1);
  Serial.println(str2);

  if (str1 == str2) Serial.println("Equals");
  else Serial.println("Different");

  if (strcmp(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

//  if (strcoll(str1, str2)) Serial.println("Equals"); // <-- this won't compile for Arduino UNO { why ??? }
//  else Serial.println("Different");

  if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
  else Serial.println("Different");

  if (areEqual(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  strcpy(str1, "test+with+spaces");
  strcpy(str2, "test with spaces");

  Serial.println();
  Serial.println(str1);
  Serial.println(str2);

  if (str1 == str2) Serial.println("Equals");
  else Serial.println("Different");

  if (strcmp(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
  else Serial.println("Different");

  if (areEqual(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  strcpy(str1, "test+with++++++++++++++++++++++++++++++++++++spaces");
  strcpy(str2, "test with spaces");

  Serial.println();
  Serial.println(str1);
  Serial.println(str2);

  if (str1 == str2) Serial.println("Equals");
  else Serial.println("Different");

  if (strcmp(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
  else Serial.println("Different");

  if (areEqual(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

}

void loop() {
  // put your main code here, to run repeatedly:

}


bool areEqual(char* string1, char* string2) {
  return ((strlen(string1) == strlen(string2)) && (strstr(string1, string2)));
}

Which produces this:

test with spaces
test with spaces
Different
Different
Different
Equals

test+with+spaces
test with spaces
Different
Equals
Equals
Different

test+with++++++++++++++++++++++++++++++++++++spaces
test with spaces
Different
Equals
Equals
Different

The first comparisson is silly (==), I know. It compares the address of the pointer, not of the string itself. I just put it there to show how hard it is for a programmer who comes from another language to understand such a thing.

The second comparison (strcmp), as the reference says "Compares the C string str1 to the C string str2.", NO, it doesn't. They are exactly the same, except for their pre-specified size. But the strings are equal to my eyes.

The third comparison (strcoll) uses locale to compare the two strings, but how come it says different when they are equal?

The fourth comparison (memcmp), given two pointers to the exact same sequence of characters, why does it say "different"?

The mind blowing part is the comparison "works" when you add as many "+" as you wish to only one of the strings. Isn't a "+" sign also a character?

It's obvious I must be missing something really basic about c++ style strings, but I dare to ask: what is it?

Thanks.

1
  • A small remark on nomenclature: The char * kind of strings are called "C strings" (careful when googling that), null- or zero-terminated strings, as they originated in C. In contrast, C++ strings are of type std::string. With these, comparison with the == operates as you expect: it compares strings, not pointers.
    – Heinrich
    Commented Oct 22, 2019 at 20:35

1 Answer 1

5

The return value of strcmp does not have boolean semantics, as you seem to incorrectly assume.

strcmp is a tri-state comparator, which returns negative, zero or positive value. For equal strings it returns zero, which means that an equality comparison with strcmp should normally look as follows

if (strcmp(str1, str2) == 0) Serial.println("Equals");
else Serial.println("Different");

while your original code actually does the opposite.

There's a moderately widespread ugly habit of writing such comparisons as

if (!strcmp(str1, str2)) Serial.println("Equals");
else Serial.println("Different");

(note the application of ! operator). It works properly, but it has poor readability. Avoid it. For tri-state comparators is a much better idea to spell out the comparison with 0 explicitly.

And you made exactly the same mistake with memcmp. memcmp is also a tri-state comparator, so it should be

if (memcmp(str1, str2, sizeof str2) == 0) Serial.println("Equals");
else Serial.println("Different");

The same applies to strcoll.

P.S. And in fact such zero-terminated strings represented by char[] arrays are called C-style strings, not C++-style strings.

1
  • Duhhh. You guys are great. In the end of the day, there was no mystic clouds around the strings, it was all about the results of the functions. Thanks.
    – MrCabana
    Commented Oct 22, 2019 at 19:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.