Go Down

Topic: Trouble manipulating comma delimited strings (Read 1 time) previous topic - next topic

jerseyguy1996

Jan 20, 2013, 05:43 am Last Edit: Jan 20, 2013, 05:47 am by jerseyguy1996 Reason: 1
I am trying to make my own string tokenizer and I am failing miserably.  Its a GPS parsing problem.  I have my sample code below but I can't get it to compile.  I am horrible with pointers and I have a feeling that is where the problem is.  Can someone help me to work my way through this please?

Code: [Select]
char buffer[] = "GPGGA,205952.987,4041.2358,N,07406.5601,W,1,05,1.9,12.1,M,-34.2,M,,0000*5C";
char messageID[6];
char time[11];
char latit[10];
char NS[2];
char longit[11];
char EW[2];
char fixindicator[2];
char satsUsed[3];
char HDOP[4];
char MSLalt[10];
char Units[2];
char Geoid[6];
char GeoUnits[2];



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

void loop()
{
int idx = 0;
idx = mytok(buffer, idx, ',', &messageID);
idx = mytok(buffer, idx, ',', &time);
idx = mytok(buffer, idx, ',', &latit);
idx = mytok(buffer, idx, ',', &NS);
idx = mytok(buffer, idx, ',', &longit);
idx = mytok(buffer, idx, ',', &EW);
idx = mytok(buffer, idx, ',', &fixindicator);
idx = mytok(buffer, idx, ',', &satsUsed);
 
}

int mytok(const char *str, int idx = 0, char sep = ',', char *target)
{
   
     while(str[idx] != sep) target++ = str[idx++];

     return idx+1;
}
Arduino Uno;
Mega328

michinyon

what does it say when you try to compile ?

If it fails to compile,  it means you have a syntax error rather than a logical error with what you
are trying to do. 

It is usually a good idea to have the definition or declaration of the function,  before you try to use it.
But this does not seem to be always necessary.

jerseyguy1996


what does it say when you try to compile ?

If it fails to compile,  it means you have a syntax error rather than a logical error with what you
are trying to do. 

It is usually a good idea to have the definition or declaration of the function,  before you try to use it.
But this does not seem to be always necessary.


This is the error messages that I get:
Code: [Select]
sketch_jan18a.cpp: In function 'void loop()':
sketch_jan18a:25: error: 'mytok' was not declared in this scope
sketch_jan18a.cpp: In function 'int mytok(const char*, int, char, char*)':
sketch_jan18a:36: error: default argument missing for parameter 4 of 'int mytok(const char*, int, char, char*)'
sketch_jan18a:39: error: lvalue required as left operand of assignment
Arduino Uno;
Mega328

lloyddean

Code: [Select]

const char buffer[] = { "GPGGA,205952.987,4041.2358,N,07406.5601,W,1,05,1.9,12.1,M,-34.2,M,,0000*5C" };

or, depending upon what you're doing
Code: [Select]

const char buffer* =  "GPGGA,205952.987,4041.2358,N,07406.5601,W,1,05,1.9,12.1,M,-34.2,M,,0000*5C";


michinyon

well your first problem may be easy.   Move the function mytok()  so it is above the function loop()  in the code.
So then,   when the compiler gets to the occurences of mytok()  inside loop(),  it alreadys knows what mytok() is.
Or put a function prototype for mytok() above loop().

I think there is some funny b/s rules about having "default values"  for function call parameters.   If you have
a default for parameter 2 and 3,  you have to have one for parameter 4.     Because the point of having
default values is so you can leave them out.   You can't leave out 2 and 3 and then have 4.

In some languages you can make calls like         y = mytok( a ,   ,   ,  d  );       but C++ is not one of them.

I'd avoid having default parameters.  They just cause trouble.



lloyddean

Code: [Select]

const char* mytok(char* pDst, const char* pSrc, char sep = ',')
{
    while ( *pSrc )
    {
        if ( sep == *pSrc )
        {
            *pDst = '\0';

            return ++pSrc;
        }

        *pDst++ = *pSrc++;
    }

    *pDst = '\0';

    return NULL;
}


Return NULL if you've reached end of string.  You can then check if you've run out of string contents.

Code: [Select]

const char*     ptr;
ptr = mytok(messageID, buffer);
ptr = mytok(time, ptr);
ptr = mytok(latit, ptr);
ptr = mytok(NS, ptr);
ptr = mytok(longit, ptr);
ptr = mytok(EW, ptr);
ptr = mytok(fixindicator, ptr);
ptr = mytok(satsUsed, ptr);
ptr = mytok(HDOP, ptr);
ptr = mytok(MSLalt, ptr);
ptr = mytok(Geoid, ptr);
ptr = mytok(GeoUnits, ptr);


lemming


jerseyguy1996


Try using the strtok function,

http://nongnu.org/avr-libc/user-manual/group__avr__string.html#ga6ace85338eafe22a0ff52c00eb9779b8

http://www.cplusplus.com/reference/cstring/strtok/

(unless you're hell bent on crafting your own)



I was originally going to use strtok but I read on one of the other forum threads that a known issue with strtok is that if you have empty fields it can screw it up so "data,data,data,,,data,data,,,,data" could have problems.  I also had a hard time figuring out how to store the various tokens for future use.  I'm not very good with pointers.....often to my detriment.
Arduino Uno;
Mega328

jerseyguy1996

Oh my....lloyddean!!!......that just works FANTASTIC!!!  And as a bonus, for once I can actually understand what you did there.  That is exactly what I was trying to do.  Thank you so much!!! And thank you everyone else for all of the great suggestions, all of which were incorporated in one way or another into my sketch.
Arduino Uno;
Mega328

Go Up