Parsing a Long from ASCII stream

Heyho, short question:

Whats the best way to parse a Long from an ASCII data stream?

Input is like:

Some useless stuff, headers etc...
<FirstValue>123</FirstValue>
<SecondVal>1565483</SecondVal>
Even more useless stuff

I tried my best with Strings, char arrays and atol, but can’t get it working…

My last try was:

// Data loop

      dataBuffer = "";
      while (client.available() > 0) {
        char inc = client.read();
        dataBuffer += inc;
        if (inc == 10) {
          getRate("<FirstValue>", 0);
          //getRate("<SecondVal>", 1);
          dataBuffer = "";
        }
      }
      delay(1000);
void getRate(String value) {
  if (dataBuffer.startsWith(value)) {
    String rate = dataBuffer.substring(value.length(), dataBuffer.indexOf("<", value.length()));
    long currentRate = rate.toInt();
    Serial.println(currentRate);
  }
}

It’s only possible to get the numbers as a String object - but if possible i do not want to use the String object anymore due to a horrible lack of memory…

Thanks and regards
Daniel

I think using strtok() with the delimiter string of “0123456789<” would work. You could convert each substring using atol().

Should be able to simply use:
long data = client.parseInt();

It returns a long in reality.

EDIT: Running your input in my test sketch shows it can parse a number that long ('scuse the pun).

I've just finished a patch for parseInt/Float which improves its behavior and hopefully will be available in 1.6.6. You can read about it here: Improvements and fixes for Stream library. by Chris--A · Pull Request #3337 · arduino/Arduino · GitHub

Nerdworld:
Heyho, short question:

Whats the best way to parse a Long from an ASCII data stream?

You start with an empty long to accumulate the number in and knowing the largest value you intend to allow to be entered, because between transmission errors and humans it's best to expect errors.

Then you do a repeated action for every digit you get that won't give you an out of bounds value.

  1. accumulator variable *= 10;
  2. add the new digit which is the text value - '0';

And you keep going as long as digits arrive and your entry stays within your bounds.

For bounds with longs I like to limit entries to 9 digits. That way the first can be 0-9 and no overflow.
Possible values are +/- over 2 billion so 999,999,999 is safe.

Note that when reading serial, this method gives you the answer where other functions just start to work. This is the code equivalent to how you write numbers on paper, not something exotic.

There's more when you're ready, start reading about state machines.

Have a look at serial input basics. It includes a parse example which should point you in the right direction.

...R

char debug[] = "<Tag>1234567890</Tag>" ;
char buff[32] = { 0 };

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

  char * tokIndex;
  
  tokIndex = strtok(debug, "<Tag>");
  strcpy(buff, tokIndex);

  long data = atol(buff) + 1;
  
  Serial.print("Test: ");
  Serial.println(data);
}


void loop() {
}

Works. :slight_smile:

@GoForSmoke:

Since it’s a machine talking to a machine (and error handling is done above) - i don’t need to validate this much - it’s also a non-critical application where a buffer overflow or a soft-reset isn’t nice - but not fatal at all. :slight_smile:

Not feeling the need to do error handling makes it easier to use the strxxx functions as well.

However reading serial and analyzing it as it comes in is still simpler, faster and uses less RAM.