Passing static char to function

Publishing char data to a function, normally you do this if it's a static definition:

mqtt_client.publish("homeassistant/sensor/blah", "parameter_value");

"homeassistant/sensor/blah" is a char*
So, if I wanted to use dynamic values on this, if it were a string you'd do:

int myval=5;
mqtt_client.publish("homeassistant/sensor/blah" + String(myval), "parameter_value");

As it's a char you'd ideally need to use strcpy to create the char array prior to using it, like this:
int myval=5;
char* publish_start = "homeassistant/sensor/blah";
char* publish_entry;
strcpy(publish_entry, publish_start);
mqtt_client.publish(publish_entry, "parameter_value");

However this seems really excessive and wasteful as for example if I was to publish 10 then I'd need 20 char values defined, stcpy each one then publish them. Is that right or am I missing something here too?

Thank you!

that would fail because you have no memory allocated to strcpy the result into

if you want to build "homeassistant/sensor/blah5" or "homeassistant/sensor/blah6" then you need to allocate a large enough buffer to hold the cString and build it up using cString functions ( see stdlib.h and string.h)

if you use the String class (not really recommended, it comes with... strings attached) you could build the right String into myString and call the mqtt_client.publish() function with myString.c_str() as a first parameter.

You can create one buffer that is slightly larger than your fixed string and then just change it as needed

char publish_start[] = "homeassistant/sensor/blah";
const int pubLength = sizeof publish_start - 1;
char publish_entry[pubLength + 5];

void setup() {
  Serial.begin(9600);
  Serial.println("Ready");
  int myval;

  strcpy(publish_entry, publish_start);

  myval = 5;
  itoa(myval, publish_entry + pubLength, 10);
  Serial.println(publish_entry);

  myval = 42;
  itoa(myval, publish_entry + pubLength, 10);
  Serial.println(publish_entry);

  myval = 12;
  itoa(myval, publish_entry + pubLength, 10);
  Serial.println(publish_entry);

}

void loop() {

}

Strings are the safer way to go, from a coding point of view. It this is an ESP32 you are already using a lot of Strings in the web libraries, so

// global constant
const char urlBase[   ] = "homeassistant/sensor/blah";

void loop() {

  int myval = 5;
  { // this block cleans up String url after it is finished with to void leaving it in memory for the whole loop()
    String url = urlBase;
    url += myval;
    mqtt_client.publish(url.c_str(), "parameter_value");
  }

As for the MQTT clients, Adafruit's does not seem to use Strings while Arduino's (beta) does.

If you are keen to use char[ ] then use strlcpy( ) strlcpy_strlcat.ino and snprintf() snprintfExample.ino methods as they check for buffer overflow (but then just truncate the result).

If you want nice error messages when your char[ ] buffer is too small use my SafeString library

No, don't. Learn how C/C++ works and use strings (nul terminated char arrays) rather than relying on some library to hold your hand and protect you

Learn how C++ works and use Strings, which were introduced to C++ 20years ago because nul terminated char arrays were so prone to coding errors.

Some great bits of info here, thank you all.
I've been trying to avoid Strings, because, well, strings! (But yes, drmpf it's esp8266 so yeah Strings everywhere!)

I went with the method J-M-L and blh64 suggested, creating the buffer with the size I needed and just re-using the char array each time, changing it with my values then publishing.

Thanks for all your help.

Long debate we already had many times.

Which you use abundantly as well as all those functions invented decades ago in your library.

There is a shared view by many here that Understanding cStrings and their pitfalls is a critical knowledge to gain if you program in C or C++ esp. for small microcontrollers.

Checking against buffer overflow, understanding the stack and heap and what happens in dynamic memory allocation will go a long way in helping anyone build better code.

Once this is acquired, if the developer chooses so, they can go to canned solutions offering more bells and whistles at the cost of more memory and CPU time and that won’t even protect them as they will still need to test if the instruction has worked anyway (after the fact rather than before the fact).

Let’s not reopen that debate.

14 posts were split to a new topic: String discussion (again)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.