9 years, 11 months ago.

Splitting a string with Float values and Character values

Having trouble splitting a data string from a SD card file. The first part will be float values (temperature), the second part is and will be character values (date and time as a string) each separated by comma's (",").

I can get the first float part (temp), however the character part (logtime) does not remove the first float part.

My data format is 19.658,01/04/14-15:35:20, (there is a carriage return character here) data then repeats.

I end up with:

temp = 19.658 (this is correct)

logtime 19.65801/04/14-15:35:20 (I need to remove the 19.658 to end up with 01/04/14-15:35:20)

Code as below:

Temp log

FILE *fp = fopen("/sd/Templogger.txt", "r");  
       
        while(fgets (buffer, 27, fp) != NULL){
            
                        
           
            temp = strtof (buffer, &pEnd);
            if(pEnd[0]==','){ pEnd[0]='0'; }
            
            logtime = strtok (buffer,",");
            
            oled.printf("%3.3f  %s  \n",temp, logtime);        
       }
       
       fclose(fp);


I know this is simple and I have tried several strtof and strtok code combinations but can't get it right.

Just in case this helps, here is the code that generates the data:

SD data record

void Temprecord()
{
    time_t seconds = time(NULL);
    strftime(buffer, 40, "%d/%m/%y-%T", localtime(&seconds));
    temp=thermom.GetTemperature();
    
    FILE *fp = fopen("/sd/Templogger.txt", "a");    
    
    fprintf (fp,"%3.3f,",temp);
    fprintf (fp,"%s,\r",buffer);
         
    fclose(fp);  
}    


Any help to do this properly would be appreciated.

My data file can be big over 1Mb and loads into Excel no problem and I'm only sampling one block of 27 characters at a time. (there is an extra carriage return character between each block for Excel to import the data in the correct format).

Many thanks

Update...

Thank you for all the answers, Erik's suggestion worked, but I will experiment with David's examples to gain more experience with string handling. Not using Linux and will keep in mind Martins advice regarding modifying strings using these function.

what does line 8 do (that replace "," by ''0") ? I wonder why strtok returns the entire string without delimeter. I assume the first call should return the first part of the string until the delimeter is reached. So in your case, second call to strtok should return the value you want (supplied by NULL as the first parameter). For more information : http://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html.

Be aware of this warning:
"Warning: Since strtok and wcstok alter the string they is parsing, you should always copy the string to a temporary buffer before parsing it with strtok/wcstok (see Copying and Concatenation). If you allow strtok or wcstok to modify a string that came from another part of your program, you are asking for trouble; that string might be used for other purposes after strtok or wcstok has modified it, and it would not have the expected value. "

posted by Martin Kojtal 02 May 2014

3 Answers

9 years, 11 months ago.

I guess you are on Windows ?

On linux, you could use SED or AWK to split string very easily.

Anthony

9 years, 11 months ago.

I guess he is on mbed.

Your problem is in line 8, you replace the comma with a '0', so if you then search for a comma, you won't find one. Then I never used strtok, but it seems to work different the first time. If line 8 is commented out, it works with this:

char* logtime = strtok (buffer,",");
logtime = strtok (NULL,",");

Wouldn't using sscanf for example be easier though?

This worked Erik, but is there a better way using sscanf or is it just another way to 'crack a nut'?

posted by Paul Staron 03 May 2014
9 years, 11 months ago.

I've used strtok successfully several times, but for some reason I cannot execute it successfully in my head - so resort to single-stepping until the rules kick back in successfully.

But I wonder if this small change gets you what you want:

    FILE *fp = fopen("/sd/Templogger.txt", "r");  
       
        // Assumes format "19.658,01/04/14-15:35:20,"
        while(fgets (buffer, 27, fp) != NULL) {
            temp = strtof(buffer, &pEnd);
            pEnd++;                 // advance past the expected ','
            p = strchr(pEnd, ',');  // find the second comma
            if (p) *p = '\0';       // and remove it
            oled.printf("%3.3f  %s  \n",temp, pEnd);
       }
       
       fclose(fp);

If your input data record is "19.658,01/04/14-15:35:20," (has a trailing ','), and you don't want that passed thru, the optional lines involving 'p' remove it.

Thank you David, I will keep this example in my collection of examples for future reference.

posted by Paul Staron 03 May 2014