multiple integers from string

I have a parameter that stores timers in seconds separated by commas. Is there a way to get each integer from the string stored as separate ints? sstring is a good example but there is no serial data as the parameter is locally stored in Eeprom.

Example:

param=10,30,12,15,22
int1=10
int2=30
int3=12
etc...

strtok along with atoi

Simple and effective. Thank you very much.
What if the size of the array is not know at the time of compiling?

Divinity82:
What if the size of the array is not know at the time of compiling?

Then you can't make legal C++ code out of it in the first place. Array sizes must be known at compile time in C++.

Please stop with contrived generalizations. If you have a piece of code you'd like to ask about then post it.

How would I get the numbers from stringParamValue and use them to control a relays on and off durations?
Example stringParamValue is 2,10,4,30 but could be as many as 300 characters.

#include <stdio.h>
#include <string.h>
#include <IotWebConf.h>

const char thingName[] = "testThing";
const char wifiInitialApPassword[] = "smrtTHNG8266";

#define STRING_LEN 128
#define NUMBER_LEN 32
#define CONFIG_VERSION "0.8.1"
#define CONFIG_PIN 2
#define STATUS_PIN LED_BUILTIN

void configSaved();
boolean formValidator();

DNSServer dnsServer;
WebServer server(80);

char stringParamValue[STRING_LEN];
char intParamValue[NUMBER_LEN];
char floatParamValue[NUMBER_LEN];

IotWebConf iotWebConf(thingName, &dnsServer, &server, wifiInitialApPassword, CONFIG_VERSION);
IotWebConfParameter stringParam = IotWebConfParameter("Relay Timing (on and off timers in seconds separated by commas  EXAMPLE: 2,4,6,8,10)", "stringParam", stringParamValue, STRING_LEN);

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println("Starting up...");

  iotWebConf.setStatusPin(STATUS_PIN);
  iotWebConf.setConfigPin(CONFIG_PIN);
  iotWebConf.addParameter(&stringParam);
  iotWebConf.setConfigSavedCallback(&configSaved);
  iotWebConf.setFormValidator(&formValidator);
  iotWebConf.getApTimeoutParameter()->visible = true;

  iotWebConf.init();

  server.on("/", handleRoot);
  server.on("/config", []{ iotWebConf.handleConfig(); });
  server.onNotFound([](){ iotWebConf.handleNotFound(); });

  Serial.println("Ready.");
  checktimers();
}

void loop() {
  // -- doLoop should be called as frequently as possible.
  iotWebConf.doLoop();
}

int checktimers() {
  char str[] = stringParamValue;
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}

void handleRoot() {
  if (iotWebConf.handleCaptivePortal()) {
    // -- Captive portal request were already served.
    return;
  }
  String s = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/>";
  s += "<title>Custom IP Parameters</title></head><body>Hello world!";
  s += "<ul>";
  s += "<li>String param value: ";
  s += stringParamValue;
  s += "</ul>";
  s += "Go to <a href='config'>configure page</a> to change values.";
  s += "</body></html>\n";

  server.send(200, "text/html", s);
}

void configSaved() {
  Serial.println("Configuration was updated.");
}

boolean formValidator() {
  Serial.println("Validating form.");
  boolean valid = true;

  int l = server.arg(stringParam.getId()).length();
  if (l < 3) {
    stringParam.errorMessage = "Please provide at least 2 timers (example: 30,15)";
    valid = false;
  }
  return valid;
}

Example stringParamValue is 2,10,4,30 but could be as many as 300 characters.

300 characters? That's not what your code says.

#define STRING_LEN 128
char stringParamValue[STRING_LEN];

What type of Arduino are you using?

What if the size of the array is not know at the time of compiling?

But in your code you do know the size of the array. It's the size of the string you don't know. That's easy because the ends of strings are marked with a null character.

I'm using an ESP32. The string length is 128 for the moment. The compiler throws an error "initializer fails to determine size of 'str' ". The string prints to serial correctly on boot.

Divinity82:
The compiler throws an error "initializer fails to determine size of 'str' ".

Yeah this isn't how you copy an array.

char str[] = stringParamValue;

Create an array the same size and memcpy it.

I don't understand. memcpy which array? I don't cuurently have a working array as the compiler doesn't know how big stringParamValue is.

Divinity82:
as the compiler doesn't know how big stringParamValue is.

Sure it does. It is defined to be 128 characters right now.

#define STRING_LEN 128
char stringParamValue[STRING_LEN];

Depending on what is actually desired, instead of this (which doesn't work)

char str[] = stringParamValue;

try

char str[STRING_LEN];
  memcpy(str,stringParamValue,strlen(stringParamValue));

or

char str[STRING_LEN];
  memcpy(str,stringParamValue,sizeof(stringParamValue));

@jremington That solved the issue. Now I need to learn more about memcpy so I can understand why it works.

I still don't understand, if the length was declared, why did the compiler not know the length... Was length not a global?

Anyway, thank you both.

if the length was declared

The length of str was not declared in your attempt.

Okay, now that I have a slightly better understanding, how do I go about isolating the tokens into declarable ints?
Do an arraylist of integers and do the Integer.valueOf?
Or something with %s?

Use strtok to pull them out of the string as tokens and then atoi to convert to integers.

Is this supposed to be done in 2 separate functions? strtok work as intended but I get 0 each time for atoi.

int checktimers(void) {
  char str[STRING_LEN];
  memcpy(str,stringParamValue,sizeof(stringParamValue));
  char * pch;
  pch = strtok (str,",");
  while (pch != NULL )
  {
    int i;
    char buffer[256];
    printf ("%s\n",pch);
    fgets (buffer, 256, stdin);
    i = atoi (buffer);
    printf ("The value entered is %d.\n",i);

    pch = strtok (NULL, ",");
  }
  return 0;
}

What's buffer for? What's it pulling from stdin? Is this for an Arduino?

I would call atoi on pch. That's the pointer to the string containing your number. That's the thing you're printing that seems to hold the right thing.

What's even in buffer? Print it and see.

I don't know what the buffer is for. I don't even know how to use atoi let alone how it works. lol
The buffer is 1073421884.
The pch is 1073421756.
The stdin is 1073440168.
It's an esp32. This is all part of the same help I was seeking in my original post.

Edit: The 1st iteration of pch contains the correct value but I don't think it is an int yet. So "fgets (buffer, 256, stdin);" is messing up or I messed it up. lol
Edit2: After looking up fgets, it does look wrong. Maybe more like this "fgets ( char * str, int 257, stdin );" and remove buffer stuff?

Oh wow. using atoi was way simpler than I was making it out to be.
int i;
i = atoi (pch);
printf ("The value is %d.\n",i);

Another question... If the size of the string can and will change, how do I know how many ints to code?

is doing a switch construct with 0 - 60 and atoi each case the best way?

Divinity82:
Another question... If the size of the string can and will change, how do I know how many ints to code?

You have to either write a function that counts them (aren't they comma delimited?) or have the sender add a number to the front of the message that tells how many are there.