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
snprintf()
. Also, you example code crashes because you access memory out of bounds of themyStrings
array. Can you give an example of how the output should look like?