michalmonday / CSV-Parser-for-Arduino

It turns CSV string into an associative array (like dict in python)
MIT License
58 stars 12 forks source link

Question: how to access individual values by using pointer to CSV_Parser? #24

Closed maze61 closed 1 year ago

maze61 commented 1 year ago

Hello Michal,

I now make extensive use of your CSV_Parser: reading list from SD card via csv files, to later display them in the UI.

Where I'm struggling: how to then access the individual values, if I'm using CSV_Parser *cpPtr later? I used the pointer in

processList( CSV_Parser *csvPtr) {
..
csvPtr->print();                 // works fine!
csvPtr->getRowsCount(); // works fine!
}

But how to access the individual values??? I tried different approaches, but with no success, because of my lack in understanding C++.

Here's my sketch:

#include <CSV_Parser.h>

#include <SPI.h>
#include <SD.h>
#include <M5Unified.h>  // ### please comment out

const int chipSelect = 10;

CSV_Parser cp1(/*format*/ "sd", /*has_header*/ true, /*delimiter*/ ',');
CSV_Parser *cp1Ptr;
const char *FileName1 = "/test.csv";

char Buf[80];  // multipurpose sprintf buffer
bool First = false;

void setup() {
  auto cfg = M5.config(); // ### please comment out
  M5.begin(cfg);          // ### please comment out

  Serial.begin(115200);
  delay(5000);

  Serial.print("Initializing SD card...");
  // see if the card is present and can be initialized:
  // if (!SD.begin(chipSelect)) {             // ### please uncomment
  if (!SD.begin(GPIO_NUM_4, SPI, 15000000)) { // ### please comment out
    Serial.println("*** Card failed, or not present");

    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");

  readLists();
}

void readLists() {  // get list values via csv parser
  if (cp1.readSDfile(FileName1)) {
    cp1.print();
    cp1Ptr = &cp1;
  }else {
    sprintf(Buf, "*** ERROR file '%s' does not exist\n", FileName1);
    Serial.print(Buf);
  }
  // more ...

}

void processList(
  CSV_Parser *csvPtr
) {
  Serial.println("*** Access via pointer to CSV_Parser");
  csvPtr->print();  // works fine!
  sprintf(Buf, "*** List has %d entries\n", csvPtr->getRowsCount());  // works fine!
  Serial.print(Buf);

  // doesn't work:"compile error: expected unqualified-id before '[' token"
  // char **strings = (char**)csvPtr->[0];
  // int32_t *numbers = (int32_t*)csvPtr->[1];

  // loader ld error: "undefined reference to `CSV_Parser::getValues(int)'"
  // char **strings = (char**)csvPtr->getValues(0);
  // int32_t *numbers = (int32_t*)csvPtr->getValues(1);

  for (int row = 0; row < csvPtr->getRowsCount(); row++) {
    // how to access the individual values now ???
    // sprintf(Buf, "%d: '%s' %d\n", row, strings[row], numbers[row]);
    // Serial.println(Buf);
  }
}

void loop() {
  if(!First) {  // invoke only once (just for test purposes)
    processList(cp1Ptr);

    First = true;
  }
}
test.csv
my_strings,my_numbers
hello,5
world,10

As I'm using M5Stack and not Arduino, may I please ask you to un/comment the lines marked with // ###.

Thank you, Marcus

michalmonday commented 1 year ago

Hello, a quick but ugly workaround would be to dereference the pointer:

char **strings = (char**)((*csvPtr)[0]);

A more elegant workaround would be to pass CSV_Parser object as a reference instead of a pointer.

The reason for the issue is that currently "[]" operators are only overloaded for the CSV_Parser object and not for a pointer of it.

maze61 commented 1 year ago

Hello Michal,

again thank you so much for your ultrafast reply!!!

Both methods work well :-)

Take care, Marcus