2

I have an Arduino that controls timers. The settings for timers are stored in byte arrays. I need to convert the arrays to strings to SET a string on an external Redis server.

So, I have many arrays of bytes of different lengths that I need to convert to strings to pass as arguments to a function expecting char[]. I need the values to be separated by commas and terminated with '\0'.

byte timer[4] {1,5,23,120};
byte timer2[6] {0,0,0,0,0,0}

I have succeeded to do it manually for each array using sprintf() like this

char buf[30];
for (int i=0;i<5;i++){ buf[i] = (int) timer[i];  }
   sprintf(buf, "%d,%d,%d,%d,%d",timer[0],timer[1],timer[2],timer[3],timer[4]);

That gives me an output string buf: 1,5,23,120 But I have to use a fixed number of 'placeholders' in sprintf().

I would like to come up with a function to which I could pass the name of the array (e.g. timer[]) and that would build a string, probably using a for loop of 'variable lengths' (depending of the particular array to to 'process') and many strcat() functions. I have tried a few ways to do this, none of them making sense to the compiler, nor to me!

Which way should I go looking?

5
  • 2
    timer[4] is out of bounds. Commented Jan 17, 2018 at 22:03
  • Possible duplicate of How to pass variable number of arguments to printf/sprintf Commented Jan 17, 2018 at 22:03
  • sprintf returns character count. You can move the pointer to buf accordingly and do the next value and so on. As long as you make sure the buffer is large enough. And add commas manually before second etc Commented Jan 17, 2018 at 22:08
  • 1
    the arduino language is C++ Commented Jan 17, 2018 at 22:51
  • The question is tagged c++, but the code (and answers) are all in c instead. A c++ solution would be to use a std::ostringstream to format the bytes in a loop. Commented Jan 18, 2018 at 4:26

2 Answers 2

3

Here is the low tech way you could do it in normal C.

char* toString(byte* bytes, int nbytes)
{
    // Has to be static so it doesn't go out of scope at the end of the call.
    // You could dynamically allocate memory based on nbytes.
    // Size of 128 is arbitrary - pick something you know is big enough.
    static char buffer[128];
    char*       bp = buffer;
    *bp = 0;  // means return will be valid even if nbytes is 0.
    for(int i = 0; i < nbytes; i++)
    {
        if (i > 0) {
            *bp = ','; bp++;
        }
        // sprintf can have errors, so probably want to check for a +ve
        // result.
        bp += sprintf(bp, "%d", bytes[i])
    }
    return buffer;
} 
Sign up to request clarification or add additional context in comments.

2 Comments

Nice - avoiding strcat() which re-walks the string. I also like to handle case when nbytes == 0, so recommend char* bp = buffer; *bp = '\0';
@chux Perfect example of how bugs creep in. All looks good, comments mention getting the size right etc, but if you passes nbytes = 0 the first time through boom. I guess the other obvious fix (left as an exercise to the reader) is null pointer check on the params.
1

an implementation, assuming that timer is an array (else, size would have to be passed as a parameter) with the special handling of the comma.

Basically, print the integer in a temp buffer, then concatenate to the final buffer. Pepper with commas where needed.

The size of the output buffer isn't tested, mind.

#include <stdio.h>
#include <strings.h>

typedef unsigned char byte;

int main()
{
   byte timer[4] = {1,5,23,120};
   int i;

   char buf[30] = "";
   int first_item = 1;

   for (i=0;i<sizeof(timer)/sizeof(timer[0]);i++)
   {
      char t[10];
      if (!first_item)
      {
         strcat(buf,",");   
      }
      first_item = 0;

      sprintf(t,"%d",timer[i]);
      strcat(buf,t);
    }

   printf(buf);

}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.