Pages: [1]   Go Down
Author Topic: Extracting data from delimited list  (Read 775 times)
0 Members and 1 Guest are viewing this topic.
New Jersey
Offline Offline
Sr. Member
****
Karma: 1
Posts: 483
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am trying to extract values from a delimited list.  The code works properly for the first loop through the code, but every pass afterward only extracts the first value; I can't figure out why it doesn't work the same every time.

Code:
#include <string.h>
char *buff;
void setup()
{
  Serial.begin(57600);
}

void loop()
{
  delay(5000);
  Serial.println("Start... ");
  buff = "10991|5:00:35p|10/20/2009|53|297|7|297|12|N/A|N/A|30.14s|66%|53°|52°|42°|51°|N/A|+0.0|+0.0|+0.00/h|81.0|51.0|30.15|30.11|N/A|4:17p|0|0|-106°|-13|0|N/A|+0.0°/h|+0.0|+0.0|300|3600|";
  char delims[] = "|";
  char *result = NULL;
  char * ptr;
  result = strtok_r( buff, delims, &ptr );
  
  int counter = 0;
  while( result != NULL ) {
    counter++;
    Serial.print(counter);
    Serial.print(": ");
    Serial.println(result);
    result = strtok_r( NULL, delims, &ptr );
  }
}

The output is:
Code:
Start...
1: 10991
2: 5:00:35p
3: 10/20/2009
4: 53
5: 297
6: 7
7: 297
8: 12
9: N/A
10: N/A
11: 30.14s
12: 66%
13: 53°
14: 52°
15: 42°
16: 51°
17: N/A
18: +0.0
19: +0.0
20: +0.00/h
21: 81.0
22: 51.0
23: 30.15
24: 30.11
25: N/A
26: 4:17p
27: 0
28: 0
29: -106°
30: -13
31: 0
32: N/A
33: +0.0°/h
34: +0.0
35: +0.0
36: 300
37: 3600
Start...
1: 10991
Start...
1: 10991
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 178
Posts: 12293
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Does this make any difference...

Code:
#include <string.h>
[glow]char buff[180];[/glow]
void setup()
{
  Serial.begin(57600);
}

void loop()
{
  delay(5000);
  Serial.println("Start... ");
  [glow]strcpy( buff, "10991|5:00:35p|10/20/2009|53|297|7|297|12|N/A|N/A|30.14s|66%|53°|52°|42°|51°|N/A|+0.0|+0.0|+0.00/h|81.0|51.0|30.15|30.11|N/A|4:17p|0|0|-106°|-13|0|N/A|+0.0°/h|+0.0|+0.0|300|3600|" );[/glow]
  char delims[] = "|";
  char *result = NULL;
  char * ptr;
  result = strtok_r( buff, delims, &ptr );
  
  int counter = 0;
  while( result != NULL ) {
    counter++;
    Serial.print(counter);
    Serial.print(": ");
    Serial.println(result);
    result = strtok_r( NULL, delims, &ptr );
  }
}
Logged

New Jersey
Offline Offline
Sr. Member
****
Karma: 1
Posts: 483
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This works better.  The only wierd thing is it's extracting the last value incorrectly.  The last value should be 3600, but the code is pulling it out as 3s00.

Code:
Start...
1: 10991
2: 5:00:35p
3: 10/20/2009
4: 53
5: 297
6: 7
7: 297
8: 12
9: N/A
10: N/A
11: 30.14s
12: 66%
13: 53°
14: 52°
15: 42°
16: 51°
17: N/A
18: +0.0
19: +0.0
20: +0.00/h
21: 81.0
22: 51.0
23: 30.15
24: 30.11
25: N/A
26: 4:17p
27: 0
28: 0
29: -106°
30: -13
31: 0
32: N/A
33: +0.0°/h
34: +0.0
35: +0.0
36: 300
37: 3s00
38: ?
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 178
Posts: 12293
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


I may have declared buff too small.  Try making it a bit bigger.

It's also possible that there isn't enough memory (SRAM) available.
« Last Edit: February 15, 2010, 12:27:27 am by bcook » Logged

Huntsville, Alabama, USA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 327
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Don't forget that strtok() modifies the string passed in.  It overwrites delimiters with NUL characters.  Passing in a pointer to a string constant (as in the first example) is not recommended, since it's not a good idea to modify constants.

-Mike
Logged

New Jersey
Offline Offline
Sr. Member
****
Karma: 1
Posts: 483
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I increased buff to 200 and now the last value in my delimited list is extracted corrctly.

What is a 'string constant'?  I'm new to this and it seems string manuplation is rather complex and not intuitive.  Is there a good beginner's resource somewhere for understanding how to use string?

Also, Mike are you said it's not a good idea to modify string constants.  Am I doing that with this code?  If so, what should I do differently?

Scott
Logged

New Jersey
Offline Offline
Sr. Member
****
Karma: 1
Posts: 483
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm glad I got this working now.  But can someone tell me why my original code didn't work.  I'd like to get a better understanding of this.

--Sctt
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 553
Posts: 46299
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mike did in reply #4. The strtok function modifies the input. So, on the second pass through loop, buff = "10991". When you parse this string, you get one value.

Making a copy of the data, as you are now doing, preserves the original, so you can copy it again.
Logged

New Jersey
Offline Offline
Sr. Member
****
Karma: 1
Posts: 483
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

But in my original code I set buff in each loop:
buff = "10991|5:00:35p|10/20/2009|...."

So even buff is changed by strtok(), why isn't buff repopulated with the whole string on the each loop.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 553
Posts: 46299
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The buff variable is a pointer. You point it to some memory location, where, coincidentally you are storing some data. The initialization of those memory locations only happens once.

The assignment statement in loop gets executed on each pass. The storing of data does not. That is, the code makes sure that buff is pointing to the same location on each pass. That the data being pointed to was modified on a previous pass is of no concern to the compiler.
Logged

Pages: [1]   Go Up
Jump to: