c_str()

Dear community,

I have a question about the following code:

String payload_2 = "1";

void setup() {
Serial.begin(74880);

}

void loop() {

const char* payload = payload_2.c_str(); // convert String into C-string

if (payload == "1") {
  Serial.println("1");
}
else if (payload == "0") {
  Serial.println("0");
}
delay(1000);

}

This code doesn't seem to print 1 to the Serial monitor(which I would expect it to do). Why is that?

Thank you guys in advanced!

Niek

and

if (payload[0] == '1') {
    Serial.println("1");
  }
  else if (payload[0] == '0') {
    Serial.println("0");
  }

  }

?
do you want to compare the pointer or the value ?
have a look at strcmp for multiple characters.

since you use a String (not the best idea), why do you feel the need to go back to the char buffer (cString)... Go all the way and use the == operator directly on your string

String message = "1";

void setup() 
{
  Serial.begin(115200);
  if (message == "1") {
    Serial.println("1");
  } else if (message == "0") {
    Serial.println("0");
  }
}

void loop() {}

if you want to use the standard basic cStrings (null terminated char array) you have access to plenty of functions in stdlib.h or string.h

char message[30] = "1"; // careful not to overflow

void setup() 
{
  Serial.begin(115200);
  if (!strcmp(message,"1")) {  // https://en.cppreference.com/w/cpp/string/byte/strcmp
    Serial.println("1");
  } else if (!strcmp(message,"0")) {
    Serial.println("0");
  }
}

void loop() {}

That seems to work, but what if I would like to enlarge the String payload_2. I have to loop through every element?

String payload_2 = "123";

void setup() {
Serial.begin(74880);
}

void loop() {

const char* payload = payload_2.c_str();

if (payload == "123") {
 Serial.println("123");
}
else if (payload == "0") {
 Serial.println("0");
}
delay(1000);

}

In my experience I have learned that a char* can refer directly to the whole C-String.

char*text = "123";


void setup() {
Serial.begin(74880);

}

void loop() {
if ( text == "123"){
 Serial.println("in if-statement");
}
else{
 //do nothing
}
delay(1000);

}

The above prints "in if-statement" to the Serial monitor. So I don't see the difference between the two scripts.
Thank you.

== on cString will compare pointers... so that won't work in the general case. Here the compiler likely saw you have twice the same cString so only allocated one and thus pointers are equal.

You want to compare what is pointed to (each character until the end of the text, which is noted by a NULL '\0' char)... You need to use strcmp()

also - you are not a newbie anymore, read the forum rules and Please correct your post above and add code tags around your code:

[code]

[color=blue]// your code is here[/color]

[/code]

.

It should look like this:

// your code is here

(Also press ctrl-T (PC) or cmd-T (Mac) in the IDE before copying to indent your code properly)

what if I would like to enlarge the String payload_2

Don't use Strings (uppercase S) in the first place, use strings (lowercase s) throughout.

As has been suggested, you can use the strcmp() function to compare 2 strings

Thank you for all the answers, but I don't quite get it.

Why does the follow code work (by working is meant printing "hello" to the Serial monitor):

const char*text = "hello";


void setup() {
  Serial.begin(74880);
}

void loop() {
  if ( text == "hello") {
    Serial.println("hello");
  }
  else {
    //do nothing
  }
  delay(1000);

}

But the following code does not:

String payload_2 = "hello";

void setup() {
  Serial.begin(74880);


}

void loop() {

  const char* payload = payload_2.c_str();

  if (payload == "hello") {
    Serial.println("hello");
  }
  else {
    //do nothing
  }
  delay(1000);

}

In both cases C-strings are used.

The first sketch works by accident :wink: If you use normal strings (aka char arrays) you can't compare them with a simple ==. The pointers to the arrays get compared. But here you are tricked by the compiler. It sees you using "hello" two times so it uses the same memory for it. So when you do the compare both 'payload' and "hello" point to the same memory. In the second version that's not the case. Now you really have two different pointers.

If you want to do real string compare use for example strcmp().

And yeah, better not to start with a String in the first place.

So I don't see the difference between the two scripts.

My view

char *text = "123";

tells the compiler that there is "123" somewhere in memory (let's say at location 0x1234) and that text is a variable that points to that "123"; so the text variable contains 0x1234.

if ( text == "123")

tells the compiler / linker that there is "123" somewhere in memory; the compiler / linker knows that "123" was already somewhere in memory and will not create a new "123" but will use "123" at address 0x1234. And hence the result evaluates to true.

The below code shows where the c_str and the "123" are located in memory. Please note that String (capital C) objects allocate memory for their internal storage, so when you assign "123" to payload_2, it makes a copy.

String payload_2 = "123";
char *text = "123";

// print buffer
char buf[64];

void setup()
{
  Serial.begin(57600);
  sprintf(buf, "c_str located at %p", payload_2.c_str());
  Serial.println(buf);
  sprintf(buf, "text located at %p", text);
  Serial.println(buf);
}

void loop()
{
}

Output

c_str located at 0x23a
text located at 0x11b

PS
Please don't use bold text for no reason.

Thank you very much I understand now!

NiekBeijloos:
Thank you very much I understand now!

that's what I tried to explain in #4 stating

== on cString will compare pointers... so that won't work in the general case. Here the compiler likely saw you have twice the same cString so only allocated one and thus pointers are equal.