1

I want to print text and numbers mixed in a table with Serial.print(); from a char array. My problem is the conversion between the different data types. My idea is to print the data of the rows in a for loop with the variable i and the columns in a for loop with the variable j.

I have in the following example two variable, one is type integer and the second is a double. Now i want to add the values of the variables into the char-array, but I can't find a way to do this...

In my main program the variables need to have this data types and should be inserted later into the char array.

Does someone have a solution for this challenge?

Here is a small example code:

int a = random(0, 100);
double b = random(0, 100);

char* myStrings[][6] = {"This is string 1", "This is string 2", "This is string 3",
                        "This is string 4", "This is string 5", "This is string 6"
                       };

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

void loop() {


  //now put the integer and double variables into the char array in the second column

  //Print the values
  for (int i = 0; i < 2; i++)
  {

    for (int j = 0; j < 6; j++)
    {
      Serial.print(myStrings[i][j]);
      Serial.print("  ");
      delay(100);
    }
    Serial.println();
  }

}

Many thanks in advance.

Guss

EDIT: The output should look like this: Headline (in this example it is the text "This is string 1", "This is string 2"...) and then the values of the variables in the next row. It should be like this:

This is String 1     This is String 2     This is String 3

Variable a           Variable b           Variable int

Variable double      Variable double      Variable int
4
  • Did I understand you correctly that you want to write an integer value into a char buffer? You can do that using snprintf(). Also, you example code crashes because you access memory out of bounds of the myStrings array. Can you give an example of how the output should look like? Jan 19, 2018 at 18:30
  • Thanks for your fast answer. I have in edit in my question above. Maybe char array isn't the best way. I'm open for improvements.
    – Guss0302
    Jan 19, 2018 at 18:52
  • Do you need the data tabulated like that, or would one item per line be ok? Tabulating it will be a bit more complicated. Still doable but harder.
    – Mark Smith
    Jan 19, 2018 at 19:23
  • It should be tabulated because the column names are different in its length.
    – Guss0302
    Jan 19, 2018 at 19:34

1 Answer 1

1

First of all, you should decide for a datastructure for you table. There are many options with various advantages and disadvantages. I am choosing a statically allocated table here, with a fixed width for each entry in the table and a fixed number of columns. One may also use pointers to strings which are allocated on the heap or elsewhere, but I find this to be the simplest.

Anyways, the basic problem doesn't change: We want to write a integer value in some string buffer. I am using the C library function snprintf() here. This function is like printf(), just that it writes its output to a given buffer of a maximum size. Thus, we can use simple format strings here and some workarounds for non-working format strings (floating points..)

Here is the code.

#include <Arduino.h>

/* A table is a 2 dimensional array of char buffers.
   The core element is a char buffer of fixed size.
   The number of columns must be fixed at compile time.
   Rows can by dynamically added in the structure without having to
   declare the number of elements.
   You can declare the number of rows at compile time, but do not need to fill them.
   Thus you can dynamically add rows to the table.
 */

#define MAX_ENTRY_SIZE 20
#define NUM_COLUMNS 3
#define COLUMN_PRINT_WIDTH MAX_ENTRY_SIZE

char myTable[][NUM_COLUMNS][MAX_ENTRY_SIZE] = {
        {"Column 1", "Column 2" ,"Column 3"}, //Row 1
        {"Variable a", "Variable b", "Variable int"}, //Row 2
        {"Variable double", "Variable double" ,"Variable double"}, //Row 1
};

char* get_table_entry(int row, int column) {
    char* entry = myTable[row][column];
    return entry;
}

void write_int_to_table(int value, int row, int column) {
    //Get a pointer to where the entry is
    char* entry = get_table_entry(row, column);
    //write a new string inside it
    snprintf(entry, MAX_ENTRY_SIZE, "%d", value);
}

void write_double_to_table(double value, int row, int column) {
    //Same as above, different format string..
    char* entry = get_table_entry(row, column);
    //Formatting floats on an Arduino Uno is tricky. %f formatters don't work (cut out due to size.)
    //use String API instead
    String stringFloat(value);
    const char* cString = stringFloat.c_str();
    strncpy(entry, cString, MAX_ENTRY_SIZE);
}

void print_table() {
    //Get number of Rows
    int numRows = sizeof(myTable) / (MAX_ENTRY_SIZE * NUM_COLUMNS);
    for(int row = 0; row < numRows; row++) {
        //Print all columns of this row
        for(int column = 0; column < NUM_COLUMNS; column++) {
            char* entry = get_table_entry(row, column);
            Serial.print(entry);
            //fill with spaces to the right
            for(unsigned int i=0; i< COLUMN_PRINT_WIDTH - strlen(entry); i++) Serial.print(" ");
        }
        Serial.println();

        //Table header seperator
        if(row == 0)
            Serial.println("============================================");
    }
}

void setup() {
    Serial.begin(9600);
    print_table();
}

void loop() {
    int a = random(0, 100);
    double b = random(0, 100);

    Serial.print("Will write new values for a = ");
    Serial.print(a);
    Serial.print(" and b = ");
    Serial.println(b);

    //write these in the second row (first row after header), first and second column.
    write_int_to_table(a, 1, 0);
    write_double_to_table(b, 1, 1);

    //Print table again
    print_table();
    Serial.println();
    Serial.println();

    delay(5000);
}

Two rounds give the output:

Column 1            Column 2            Column 3
============================================
Variable a          Variable b          Variable int
Variable double     Variable double     Variable double


Will write new values for a = 7 and b = 49.00
Column 1            Column 2            Column 3
============================================
7                   49.00               Variable int
Variable double     Variable double     Variable double
2
  • Wow, very impressive. Thanks a lot for this code. One little question, how can I print the table head seperator to the length of the table head automatically?
    – Guss0302
    Jan 19, 2018 at 19:48
  • 1
    You can calculate the number of needed characters by doing int num = NUM_COLUMNS * MAX_ENTRY_SIZE, then print the seperator character in a for loop from 0 to num. Jan 19, 2018 at 19:50

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.