String with variable of fixed lenght

I want to email a formatted text containing a table of variables that may contain -1 to 1024 Values.

I need to use the String function to provide a string to the function sending.

But don't know how to be sure the spacing in the table stays correct when the variables have different lengths.

My idea was to space them 4 places and to fill smaller variable lengths with leading 0 or spaces (which would be better).

But I don't know how to add leading spaces to my variables depending on their lenght.

Any Idea?

Is there any function for filling spaces in a String?

Gorkde:
I want to email a formatted text containing a table of variables that may contain -1 to 1024 Values.

I need to use the String function to provide a string to the function sending.

But don't know how to be sure the spacing in the table stays correct when the variables have different lengths.

My idea was to space them 4 places and to fill smaller variable lengths with leading 0 or spaces (which would be better).

But I don't know how to add leading spaces to my variables depending on their lenght.

Any Idea?

Would someone care to explain sprintf ?

Thanks very much, seems exactly what I need!

Another question regarding this.

How do I create the char Array for a variable size of my string to fill?

you might need to use malloc, to allocate memory dynamically. free the memory once you done with it.

Thanks!

Just use a variable of sufficient size. You know exactly how big it should be maximum (size of some text plus 4 characters plus terminating nul).

So for "hello 1024" you need a buffer of 5 + 1 + 4 + 1 = 11 characters.

sprintf(buffer, "hello %d", yourVariable);    // 'normal' print
sprintf(buffer, "hello %4d", yourVariable);   // print with leading spaces
sprintf(buffer, "hello %04d", yourVariable);  // print with leading zeroes

Yes I think that's way more easy (just took a variable size of 1000 for testing purposes).

I could write

printf("SensorData:%5d" "%5d" "%5d", MyArray[0],  MyArray[1],  MyArray[2]);  // and so on...

But that would result in a huge line and would be somewhat clumpy.

Also I would like to stop output at the maximum number of used sensors (which may differ from maximum possible sensors - see last line below in my example).

So I need to create a string containing the sensor-number line, then a line with 10 sensor data as long as Sensors >= 10, then continue with the next line and so on.

As soon as the last sensor is reached I want him to stop that line at that place.

Then after that I would like him to add all lines to a long string to support to my function (if that isn't wasting huge ammounts of memory for many Arrays).

Like at the end of my sketch below.

I already tested with printf() and it works with me putting that in one line by hand. But I really don't know how to put all the sensor readings in one string or one string per line automatically.

I don't understand if I need to define a 2 dimensional array to fill (like I started to try above my test) or some pointer to a one dimensional Array or so on....

I in general know what pointers are from programming assembly but somehow I can't get it in C.

I stopped writing my for statement since I'm pretty sure I'm on the wrong path somehow....

// ----- Error Email Body definition ------------------------------------------------------
#define Zeile2 "\nLETZTE MESSWERTE:\n\n"
#define Zeile4 "Wasserstand Tank: "
#define Zeile5 "Wasserstand D-Mix: "
#define Zeile6 "Temperatur (°C): "
#define Zeile7 "Helligkeit: "
// \n
// \n
#define Zeile10 "Feuchtigkeitssensoren:\n"
#define ZeileTrenn "___________________________________________________________\n"
#define Zeile12 "Topf:        1    2    3    4    5    6    7    8    9   10\n"
#define Zeile13 "Messwert:  100  100  100  100  100  100  100  100  100  100\n"
// ---
#define Zeile15 "Topf:       11   12   13   14   15   16   17   18   19   20\n"
#define Zeile16 "Messwert:  100  100  100  100  100  100  100  100  100  100\n"
// ---
#define Zeile18 "Topf:    "
#define Zeile19 "Messwert:"
// ---
#define Zeile21 "Topf:       31   32   33   34   35   36   37   38   39   40\n"
#define Zeile22 "Messwert:  100  100  100  100  100  100  100  100  100  100\n"
// ---
#define Zeile24 "Topf:       41   42   43   44   45   46   47   48   49   50\n"
#define Zeile25 "Messwert:  100  100  100  100  100  100  100  100  100  100\n"
// ---
#define Zeile27 "Topf:       51   52   53   54   55   56   57\n"
#define Zeile28 "Messwert:  100  100  100  100  100  100  100\n"
// ---
// \n
// \n
#define Zeile32 "Hinweis: Sensorfehler oder fehlende Kalibration = -1"
// ----------------------------------------------------------------------------------------

int TestValue1 = 100;
int TestValue2 = 2;
int TestValue3 = 60;

int NoSens = 16;                    // 16 Sensors of 56 possible
char MailString[1000] = {};         // Entire String for output
char TestArray[6][59] = {};         // Lines for output                   

int SensorReadings[56] = {
  270, 400, 600, 770, 270, 400, 600, 770,
  270, 400, 600, 770, 270, 400, 600, 770,
  270, 400, 600, 770, 270, 400, 600, 770,
  270, 400, 600, 770, 270, 400, 600, 770,
  270, 400, 600, 770, 270, 400, 600, 770,
  270, 400, 600, 770, 270, 400, 600, 770,
  270, 400, 600, 770, 270, 400, 600, 770
};

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

void loop()
{
  /*
    for (int i = 0; < 6 ; i++)
    {
      for (int j = 0; < 10)
      {
        if(j < NoSens)
        {
        TestArray[i][j] = sprintf("Messwert:%5d"  );    // And so on....
        }
        else
        {
          TestArray[i][j] = "\n" // If last pot reached
        }
      }
    }
  */

  Serial.println("\n\n\n---------------------------------------------------------------------------------------------");

  printf(Zeile2 Zeile4 "%d\n" Zeile5 "%d\n" Zeile6 "%d\n" Zeile7 "%d\n\n\n" Zeile10
         ZeileTrenn Zeile12 Zeile13 ZeileTrenn Zeile15 "Messwert:%5d" "%5d" "%5d"
         , TestValue1, TestValue2, TestValue3, TestValue1, TestValue3, TestValue2, TestValue1);


  delay(5000);
}





/*
  // ----- Needed Email Body  ------------------------------------------------------
  #define Zeile1 "\n"
  #define Zeile2 "LETZTE MESSWERTE:\n"
  #define Zeile3 "\n"
  #define Zeile4 "Wasserstand Tank: "
  #define Zeile5 "Wasserstand Düngermix: "
  #define Zeile6 "Temperatur (°C): "
  #define Zeile7 "Helligkeit: "
  #define Zeile8 "\n"
  #define Zeile9 "\n"
  #define Zeile10 "Feuchtigkeitssensoren:\n"
  #define Zeile11 "___________________________________________________________"
  #define Zeile12 "Topf:        1    2    3    4    5    6    7    8    9   10"
  #define Zeile13 "Messwert:  100  100  100  100  100  100  100  100  100  100"
  #define Zeile14 "___________________________________________________________"
  #define Zeile15 "Topf:       11   12   13   14   15   16   17   18   19   20"
  #define Zeile16 "Messwert:  100  100  100  100  100  100  100  100  100  100"
  #define Zeile17 "___________________________________________________________"
  #define Zeile18 "Topf:       21   22   23   24   25   26   27   28   29   30"
  #define Zeile19 "Messwert:  100  100  100  100  100  100  100  100  100  100"
  #define Zeile20 "___________________________________________________________"
  #define Zeile21 "Topf:       31   32   33   34   35   36   37   38   39   40"
  #define Zeile22 "Messwert:  100  100  100  100  100  100  100  100  100  100"
  #define Zeile23 "___________________________________________________________"
  #define Zeile24 "Topf:       41   42   43   44   45   46   47   48   49   50"
  #define Zeile25 "Messwert:  100  100  100  100  100  100  100  100  100  100"
  #define Zeile26 "___________________________________________________________"
  #define Zeile27 "Topf:       51   52   53   54   55   56   57"
  #define Zeile28 "Messwert:  100  100  100  100  100  100  100"
  #define Zeile29 "___________________________________________________________"
  #define Zeile30 "\n"
  #define Zeile31 "\n"
  #define Zeile32 "Hinweis: Sensorfehler oder fehlende Kalibration = -1"
  // ----------------------------------------------------------------------------------------
*/

I don't know how email functionality works on an Arduino (never looked at it) but can't you just break it up in smaller chunks before sending it to the shield?

To add array values to a buffer, you could use something like below

// clear buffer; basically also guarantees that there will be a nul character
memset(buffer, 0, sizeof(buffer));

strcpy(buffer, "Messwert:");

// loop through array
for(int cnt=0;cnt<10;cnt++)
{
  sprintf(&buffer[(cnt*5) + strlen("Messwert:")], "%5d", sensorValues[cnt]);
}

The result will look something like

Messwert:   33   -1  400   12  100  100  100  100  100  100

I got a library function which want's a string as email body parameter. So it would be best to have one large string containing the entire body.

So if understand correctly buffer needs to be a one dimensional array of the size of one line +\n +1 right?

Yes

But what does the reference operator do. As said I can't really wrap my mind around Pointers in C.

printf(MailString);

Gives printf the pointer to the first char of the mailstring as parameter right?

So what does &buffer provide then?

Wouldn't

buffer[(cnt*5) + strlen("Messwert:")]

provide the pointer to that address which it needs to continue to append the next item?

Why & ?

I mean if

MailString

provides the pointer to the first char

MailString[3]

should provide the one to the 4th ?

And i got another question....

I noticed buffer is marked by Arduino IDE and read on some website buffer is allocated dynamicly while execution.

Therefore am I right I don't need to define the array but could just use "buffer" insted and it will take care of the lenght itself?

No need to answer I think I got it....

So I can either do

strcpy(MailString, Zeile2);
strcpy(MailString+sizeof(Zeile2)-1, Zeile4);
...

or the same with sprintf()

right?

Ok to finish I need another help:

I wrote:

sprintf(MailString, Zeile1 ZWass "%d\n" ZTemp "%d\n" ZLight "%d\n" ZSensTitle ZTrenn ZPot, WassMAP, Temperatur, Helligkeit);

But how do I now calculate where to continue filling in dynamically?

Gorkde:
But what does the reference operator do. As said I can't really wrap my mind around Pointers in C.

printf(MailString);

Gives printf the pointer to the first char of the mailstring as parameter right?

So what does &buffer provide then?

Wouldn't

buffer[(cnt*5) + strlen("Messwert:")]

provide the pointer to that address which it needs to continue to append the next item?

Why & ?

I mean if

MailString

provides the pointer to the first char

MailString[3]

should provide the one to the 4th ?

&buffer[n] gives you the address in memory of the n-th element in buffer.

I also suggest that you ignore the highlighting. I doubt very much that the code knows 'buffer' if it's not declared.

No

Delta_G:
strlen?

Yes but that seems pretty long for just finding the end.

Is there no simpler way?
Maybe somehow remember that last address?

I thought searching for the ending zero but since my String also might contain zeroes this won't work

There is a difference between the ascii character 0 ('0') and the number 0 (0 or '\0').

And strlen() does exactly what you want to do; count characters till it finds a '\0'. Why re-invent the wheel?

So I could do strlen(Mailbody)?

I assumed I have to re-provide all the substrings!