Detecting and converting parts of a string

I'm having a hard time with this. I have a file with the following data in it:

clouds.dat|1000|0.5 longname.dat|250|5 earth.dat|750|0.25

I'm using the following piece of code to split that apart:

  // fileData is coming from an SD read
  char *p = fileData;
  char *str;
  while ((str = strtok_r(p, "|", &p)) != NULL) {
    Serial.println(str);
  }

That's all dandy and it spits out the individual parts to the console as told. However, what I need is actually a way to assign those values to variables so that I get:

char fileName[12] = "clouds.dat";
int refresh = 1000;
float timeout = 0.5;

Additionally, that third variable can be either a float or an int in the file. As far as the coding is concerned, it needs to check whether it's a float or not. If it's a float, it gets multiplied by 1000 and converted to an int, and if it's already an int, leave it as is.

Any pointers will be appreciated here.

First. strtok_r() is the thread-safe version of strtok(). Do you really need to be using the more complicated function on a single-threaded system? The strtok() function has a smaller footprint, too.

The pointer returned by strtok() must be copied/converted before the next call to strtok(). You can use strcpy() to assign a new value to fileName. You can use atoi() and atof() for the other values.

How is the file stored, how do you access it, and how are you putting it into a variable?

PaulS:
First. strtok_r() is the thread-safe version of strtok(). Do you really need to be using the more complicated function on a single-threaded system? The strtok() function has a smaller footprint, too.

It came from an example I found online. strtok() works just fine.

PaulS:
The pointer returned by strtok() must be copied/converted before the next call to strtok(). You can use strcpy() to assign a new value to fileName. You can use atoi() and atof() for the other values.

So pardon me for having had to search for more info and examples on those but, this is what I came up with that appears to work:

char *filename = strtok(fileData, "|");
refresh = atoi(strtok(NULL, "|"));
timeout = atof(strtok(NULL, "|"));

This gives me the respective values I need in those variable. However, two questions:

  • Why does only the first ‘strtok’ use the incoming string while the other two use NULL? I discovered that if I don’t set it to NULL it doesn’t work correctly, but I don’t understand why.

  • And second, how can I determine if the last value (timeout) is a float or int when I first pull it out? Right now I’m forcing it to a float, but I need a way to detect whether it actually is or not because the next step in the code is to either multiply it by 1000 if it is a float, or use it as is.

zoomkat:
How is the file stored, how do you access it, and how are you putting it into a variable?

It’s on an SD card and I read a full line at a time with fgets() (from SdFat)

char fileData[50];
...
fileStatus = cntlFile.fgets(fileData, size of(fileData));

This gives me the full line in fileData that I can then manipulate. I can also just spit it out to the console as is and see what it actually read in.

how can I determine if the last value (timeout) is a float or int when I first pull it out?

How do you determine that when you look at the number ? Can you use the same method using the Arduino ?

KirAsh4:

  • Why does only the first ‘strtok’ use the incoming string while the other two use NULL? I discovered that if I don’t set it to NULL it doesn’t work correctly, but I don’t understand why.

http://www.cplusplus.com/reference/cstring/strtok/:
a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.

Other solutions are sscanf and regular expressions