Optimizing Code in sprintf() Arguments

snprintf(payload, sizeof(payload), "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", timestampChar, weightMedianChar,temperatureChar[0],humidityChar[0],temperatureChar[1],humidityChar[1],temperatureArrayChar[0],temperatureArrayChar[1],temperatureArrayChar[2],temperatureArrayChar[3],temperatureArrayChar[4],temperatureArrayChar[5],temperatureArrayChar[6],temperatureArrayChar[7],temperatureArrayChar[8],temperatureArrayChar[9],temperatureArrayChar[10],temperatureArrayChar[11],voltageChar);

I have this ugly and long line of code to make a char out of different variables. How can I make it a bit more pretty and parameter based?

The "%s,%s,%s,%s, ..." part can I replace with a char variable that makes automatically as many %s or other placeholder as I need.

Complicated is the variable part. how can I say "Take in the sprintf as variables timestamp, weight then

  • 2x temp and hum
  • 12x tempArray

??

I would be tempted to put the variables in a struct, then use a union to make the struct equivalent to an array, and then use a loop with strcat(...) or strncat(...) to process the variables in the array. However, that is just me. There may be an easier way.

I can't see the details because the code hasn't been posted, but I don't understand why snprintf(...) is being used on a bunch of strings.

Good Luck!

something like this?

strcat(payload, timestampChar);
strcat(payload, ",");
strcat(payload, weightMedianChar);
strcat(payload, ",");
for (int i=0; i<12; i++)
{
  strcat(payload, temperatureChar[i]);
  strcat(payload, ",");
  strcat(payload, humidityChar[i]);
  strcat(payload, ",");
}

strcat(payload, voltageChar);

You probably don't want %s - that calls for a nul terminated string, you probably want %c which just expects a single char.

Which suggests a solution, just put all your chars in an array and put a '\0' at the end. then a single %s will print it. It is ugly, but:

char buf[16] = "X,X,X,X,X,X," // automatically nul terminated...
buf[0] = char1;
buf[2] = char2;
//...

%s - the full string is right in my case. It looks scary but the reason is I need a single char with all this variables for a radio payload that requires char. It could also handle struct but with a struct you are not as flexible as with CSV in the payload. For different nodes with different variables you have to modify only the node, not the gateway also. I can not use sprintf with my float variables because Arduino doesn't support floats with sprintf, so I rounded and converted my initial floats with dtostrf. That's the reason why I deal with chars in this special case.

strcat, yes of cause! I was so focused on the sprintf function that I spend no thought on an other function to solve this. Thanks Rob and all other for your comments and hints!

but the reason is I need a single char with all this variables

Nonsense. A "single char" holds exactly that. ONE SINGLE CHARACTER.

An array of chars is a completely different story.

Sorry, Paul, "array" is missing in my post "a single character array".

Show us the rest of the code. Where and how are all those things you want to put in that char array defined and populated? It could be as simple as starting off with one large char array with slots designated for those things instead of having them all in separate variables and then trying to concatenate them into one string.

Due to the file size code is attached. The single values come from different libs. For me it is also a kind of wasting resources to have the value at least three times (or four times in case you count the raw value) in the sketch, (1) raw value, (2) float in an appropriate metric, (3) rounded and converted in char (4) aggregated in the char array

Btw. the attached sketch is in this version not fully working, the RFM lib supports only 63 bit payload, so the example payload is too big. This is a special case where I have to use struct and get rid of decimal places by multiplying, also unix timestamp is here better than human readable. By using struct I have to “know” the struct on the gateway side too. So I’m not as flexible as I want to be. Because of this I want to avoid struct whenever possible and use the default char array.

optimizing-sprintf.ino (17.5 KB)

My point was that 3 and 4 could be the same thing. Instead of saving the rounded and converted values each in their own array, set up one large array and some pointers to the various locations where those things need to go in it.

  snprintf(payload, sizeof(payload), "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", timestampChar, weightMedianChar,temperatureChar[0],humidityChar[0],temperatureChar[1],humidityChar[1],temperatureArrayChar[0],temperatureArrayChar[1],temperatureArrayChar[2],temperatureArrayChar[3],temperatureArrayChar[4],temperatureArrayChar[5],temperatureArrayChar[6],temperatureArrayChar[7],temperatureArrayChar[8],temperatureArrayChar[9],temperatureArrayChar[10],temperatureArrayChar[11],voltageChar);

Is your damned enter key broken? This is plain stupid. There is NO advantage to putting all the code on one line, making is too damned hard to read.

There is NO reason to be using snprintf() to do nothing but string manipulation. Using strncat() instead.