Convert string with data to 3 values

Hi
I recently stumbled on a problem in which I cant convert a string from a python controller to 3 values! I have had this problem but then I decided to just not deal with it, but now I really need to split the string!
The string looks like this:

 -96  -48  -992   -96  -48  -992   -96  -48  -992  ...

I for now have put spaces in between the important values but I can put commas or whatever I need!

I have not yet started the code yet but I can just tell it's going to be a nightmare!

look up strtok()

What has this got to do with installation and troubleshooting?

Using space for a delimiter is fine, but, if possible, a delimiter to separate sets of values would make decoding a bit easier. Maybe a line feed would make sense.
-96 -48 -992/n -96 -48 -992/n -96 -48 -992/n ...

Are the values coming in over the serial port? The serial input basics tutorial may be of interest. Look at example #2 to receive values with an end marker (\n in this case). And example #5 for parsing the input string using the strtok() function.

The strtol() function parses (long) integers and is able to set a pointer behind the parsed value.

That way it is easy to parse a delimited sequence of values.

void skipWs(char*& buf) {
  while (isspace(*buf)) {
    buf++;
  }
}

/** parse an int parameter

 	advance over whitespace and parse with strtol,
 	then advance over whitw space again.
 	If some data is left, assign the pointer to the input pointer
 	@param buf [out] reference of const char pointer
*/
int32_t getVal(const char*& buf) {
  char* behind = nullptr;
  skipWs(buf);
  uint32_t val = strtol(buf, &behind, 0);
  skipWs(behind);
  if (behind != nullptr) {
    buf = (const char*)behind;
  }
  return val;
}

One should always test code before posting, so here is a working example:

const char tBuf[] = "-96  -48  -992   -96  -48  -992   -96  -48  -992";

void setup() {
  Serial.begin(115200);
  const char* ptr = tBuf;
  uint8_t count = 0;
  while (*ptr) {
    Serial.print(++count);
    Serial.write(':');
    int32_t result = getVal(ptr);
    Serial.println(result);
  }
  Serial.print(F("found "));
  Serial.print(count);
  Serial.println(F(" numbers."));
}

void loop() {}

void skipWs(char*& buf) {
  while (isspace(*buf)) {
    buf++;
  }
}
/** parse an int parameter

   advance over whitespace and parse with strtol,
  then advance over whitw space again.
  If some data is left, assign the pointer to the input pointer
  @param buf [out] reference of const char pointer
*/
int32_t getVal(const char*& buf) {
  char* behind = (char*)buf;
  skipWs(behind);
  uint32_t val = strtol(behind, &behind, 0);
  skipWs(behind);
  if (behind != nullptr) {
    buf = (const char*)behind;
  }
  return val;
}
1:-96
2:-48
3:-992
4:-96
5:-48
6:-992
7:-96
8:-48
9:-992
found 9 numbers.

It's coming through the TX and RX pins!

But will this work with changing digits? (sorry didn't mention that)

The algorithm works via Serial without a problem,
I made it a bit more error resilient.

I shifted the burden of collecting the line to a class.

#include <WhandallSerial.h> // https://github.com/whandall/WhandallSerial
void procLine(const char* buf);

SSerial con(Serial, procLine);

void setup() {
  Serial.begin(115200);
  con.begin(64, optIgnoreLF + optSkipWS);
}

void procLine(const char* buf) {
  uint8_t count = 0;
  while (*buf && (*buf == '-' || isDigit(*buf))) {
    Serial.print(++count);
    Serial.write(':');
    int32_t result = getVal(buf);
    Serial.println(result);
  }
  Serial.print(F("found "));
  Serial.print(count);
  Serial.println(F(" numbers."));
}

void loop() {
  con.loop();
}

void skipWs(char*& buf) {
  while (isspace(*buf)) {
    buf++;
  }
}
/** parse an int parameter

   advance over whitespace and parse with strtol,
  then advance over whitw space again.
  If some data is left, assign the pointer to the input pointer
  @param buf [out] reference of const char pointer
*/
int32_t getVal(const char*& buf) {
  char* behind = (char*)buf;
  skipWs(behind);
  uint32_t val = strtol(behind, &behind, 0);
  skipWs(behind);
  if (behind != nullptr) {
    buf = (const char*)behind;
  }
  return val;
}
1:-96
2:-48
3:-992
4:-96
5:-48
6:-992
7:-96
8:-48
9:-992
found 9 numbers.

from -96 -48 -992 -96 -48 -992 -96 -48 -992 input.

and what happens if the values go positive?

Did you try?

1:1
2:2
3:3
4:4
5:897654
found 5 numbers.

Also, strtol() has documentation.

For the rather simple case of decimal long integers separated by blanks,
you could convert the stream directly to numbers, without any buffering.

You will not have the flexibility of the strtol() function,
but it's quite simple and uses very little RAM.

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

uint8_t numVals = 0;
uint8_t numDigits = 0;
bool minusSign = false;
int32_t accumulator = 0;

void loop() {
  if (Serial.available()) {
    char cur = Serial.read();
    if (isDigit(cur)) {
      numDigits++;
      accumulator *= 10;
      accumulator += cur - '0';
    } else {
      switch (cur) {
        case 10:  // ignore LF
          break;
        case '-':
          minusSign = true;
          break;
        case 13:  // end of line
        case ' ': // delimiter
          if (numDigits) {
            numVals++;
            if (minusSign) {
              accumulator = -accumulator;
            }
            Serial.print(numVals);
            Serial.write(':');
            Serial.println(accumulator);
            numDigits = 0;
            minusSign = false;
            accumulator = 0;
          }
          if (cur == 13) {
            Serial.print(F("found "));
            Serial.print(numVals);
            Serial.println(F(" numbers."));
            numVals = 0;
          }
      }
    }
  }
}

@adrianskalni, Your topic has been moved to a more suitable location on the forum. Installation and Troubleshooting is not for problems with (nor for advise on) your project :wink: See About the Installation & Troubleshooting category.