Question about strcmp()

I am trying to be a good programmer and learn to not use the String class.
Mostly out of necessity because my current project is using a lot of RAM in Strings.

Background, and why I didn't post my whole sketch.
I have an old-style rotary telephone dial with a Wemos D1 Mini counting the pulses then sending the dialed number to an Arduino Uno over I2C. In my original sketch, dialedNumber was initialized as a String. And the sketch works. But I need to free up more RAM - thus I am trying to convert my Strings to strings. If you need to see the whole sketch, I will post it, but it is pretty big.

In the code segment below, the receiveEvent function receives the characters dialed and the numbers accumulate in the char array dialedNumber.
When I dial "01", dialedNumber contains "01" terminated with '\0'.

My problem is how to use strcmp() in the function processDialedNumber().
I have tried

if (strcmp(dialedNumber, "03")) return 3;
if (strcmp(&dialedNumber, "03")) return 3;
if (strcmp(*dialedNumber, "03")) return 3;

but they all return 1, where I should get 3.

I am certain that the pointer to dialedNumber array is my problem, but I can't figure out what I am doing wrong.

Any tips would be appreciated.

Here's the functions inivolved:

char dialedNumber[11] = {0};            //The phone number string from the dialer
int soundIndex;                         //Index of the sound file


//---------------------- processDialedNumber() ----------------------
int processDialedNumber() {
  //Handle the phone number string received from the dialer (I2C Master).
  if (strcmp(dialedNumber[0], "01")) return 1;
  if (strcmp(dialedNumber[0], "02")) return 2;
  if (strcmp(dialedNumber[0], "03")) return 3;
  if (strcmp(dialedNumber[0], "04")) return 4;
  if (strcmp(dialedNumber[0], "05")) return 5;
}



//---------------------- receiveEvent() ----------------------
// function that executes whenever data is received from master
void receiveEvent(int howMany) {
  byte i = 0;
  char c;
  while (0 < Wire.available()) {
    c = Wire.read();                          //receive byte as a character
    dialedNumber[i++] = c;
  }
  dialedNumber[i] = '\0';                     //Terminate the accumulated string


  soundIndex = processDialedNumber();

  Serial.println();
  Serial.print(F("dialed= "));
  Serial.println(dialedNumber);

  Serial.print(F("soundIndex= "));
  Serial.println(soundIndex);

  dialedNumber[0] = '\0';                    //Ready for the next number..
}

Try:
if (strncmp( &dialedNumber[0], "01", 2 )) return 1;
and:
if (strncmp( dialedNumber, "01", 2 )) return 1;

"dialedNumber[0]" is not a pointer.

jremington:
"dialedNumber[0]" is not a pointer.

&dialedNumber[0], as he presented, IS a pointer...

Regards,
Ray L.

The correct syntax is:

strcmp(dialedNumber, "03")

Your logic is just not quite correct.
strcmp() returns a non-zero value if the 2 cstrings are not matched. And non-zero value is interpreted as true in the if().

&dialedNumber[0], as he presented, IS a pointer

Correct, but that has NOTHING to do with my comment.

I suppose I must elaborate. This is not correct, because "dialedNumber[0]" is not a pointer.

  if (strcmp(dialedNumber[0], "01")) return 1;

Are we all on the same page, now?

arduino_new:
The correct syntax is:

strcmp(dialedNumber, "03")

Your logic is just not quite correct.
strcmp() returns a non-zero value if the 2 cstrings are not matched. And non-zero value is interpreted as true in the if().

Thanks for this. How totally illogical. All these years I thought that (x==x) returned a 1. But apparently strcmp(x,x) returns a 0.

This works as expected:

int processDialedNumber() {
  //Handle the phone number string received from the dialer (I2C Master).
  if (!strcmp(dialedNumber, "01")) return 1;
  if (!strcmp(dialedNumber, "02")) return 2;
  if (!strcmp(dialedNumber, "03")) return 3;
  if (!strcmp(dialedNumber, "04")) return 4;
  if (!strcmp(dialedNumber, "05")) return 5;
  if (!strcmp(dialedNumber, "17135551212")) return 6;   //1-713-555-1212
  if (!strcmp(dialedNumber, "411")) return 7;
  return 99;                                            //If nothing matches
}

I wrote a test script to demonstrate the logic:

void setup() {
  Serial.begin(115200);
  Serial.println();

  ////--------------------- Comparing Strings --------------------
  String i = "03";
  String j = i;
  Serial.print(F("i= '"));
  Serial.print(i);
  Serial.print(F("', j= '"));
  Serial.print(j);
  Serial.println(F("'"));

  Serial.print(F("(i == j) returns: "));
  Serial.println(i == j);

  Serial.println();


  //--------------------- Comparing char arrays --------------------
  char x[4] = {'a', 'b', 'c', '\0'};
  char y[4] = {'a', 'b', 'c', '\0'};

  //char *strcpy(char *dest, const char *src)
  //Copies the string pointed to, by src to dest.
  char *strcpy(char *y, const char *x);
  Serial.print(F("x= '"));
  Serial.print(x);
  Serial.print(F("', y= '"));
  Serial.print(y);
  Serial.println(F("'"));

  Serial.print(F("strcmp(x,y); returns: "));
  Serial.println(strcmp(x, y));

}

void loop()
{
}

Once I master C strings, I will have to drop "Newbie" from my sig.
Maybe, '2nd year'.

I think you should understand what it is that strcmp() returns. It's not a boolean:
http://www.cplusplus.com/reference/cstring/strcmp/

Returns an integral value indicating the relationship between the strings:

| return value | | indicates |
| - | - |
| ------------ | ------------------------------------------------------------------------------ |
| <0 | | the first character that does not match has a lower value in ptr1 than in ptr2 |
| ------------ | ------------------------------------------------------------------------------ |
| 0 | | the contents of both strings are equal |
| ------------ | ------------------------------------------------------------------------------ |
| >0 | | the first character that does not match has a greater value in ptr1 than in ptr2 |

Given the designer's intention to return this information, you can see that 0 meaning an exact match was indeed logical. I suppose this information would be used for lexicographical sorting.

There is logic to the strcmp result, it's just very esoteric at this point in time :slight_smile: From an assembly programmer's perspective, the name implies that the operation is similar to subtraction, because usually the CPU instructions cmp and sub are the same operation except cmp doesn't write out the result anywhere (just sets the CPU flags for subsequent conditional instructions to respond to). And since x - y is zero if the values are equal, negative if x is less than y, and positive if x is greater than y, the strcmp return value makes sense.

1 Like

There is logic to the strcmp result, it's just very esoteric at this point in time

Perhaps, if you think "alphabetical order", "dictionary order" or "numerical order" is esoteric. Most people don't.