Help with pointers and character arrays

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am working on a project, where I have to read a serial NMEA sentence from a Ublox GPS unit, parse the string into multiple parts separated by a "," and then do different things with those parts.

I have found a thread from 2008, where a user called glitch has posted a solution using a bunch of pointers, which does exactly what I want, however I am having a very hard time understanding how that works. If I understand correctly, it is creating a pointer array called "parts[]", which points to different places in the original string.

Now if I want to print one of those parts I can simply call Serial.print(parts[0]) and it works and output "$GPRMC" in the example. (Note that I am actually duing this in Arduino for some other reasons)

However the thing am having trouble with is trying to compare, whether parts[0] is indeed equal to "$GPRMC", so that I'm not reading the wrong data from the GPS.

Now the solution to this would be I think to copy this "$GPRMC" part to its own array and compare it byte by byte, to see if it matches or not. But because of this whole pointer situation I don't know how to do this.

There might also be other better solution, soo if anyone can help with this, please do.

 

Here is the link to the original thread and the code I am talking about:

 

https://www.avrfreaks.net/forum/parsing-string

 

char test_string[] = "$GPRMC,161229.487,A,3723.2475,N,12158.3416,W,CHKSUM";
char *parts[15];

int main(void) {
  char *nmea = test_string;
  char **token = parts;

  // first scan for the '$' to find the start of the string
  while((*nmea) && (*nmea != '$')) nmea++;
  *token++ = nmea;

  // scan & separate the fields
  while(*nmea)
  {
    if(*nmea==',')
    {
      *nmea++ = 0;
      *token++ = nmea;
    } else nmea++;
  }
  *token++ = NULL;

   for (;;);
}

 

Edit: Realised I should have posted in Compilers and General Programming

Last Edited: Sun. Sep 9, 2018 - 05:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You haven't allocated any storage for the 15 pointers in the parts[] array? As soon as you start doing *token++ = names very very bad things will happen!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

That function also replaces the commas by zero. BTW, probably I would write:

 

      *nmea++ = '\0';

to make the intent more clear. So they become proper zero terminated strings, meaning you could use strcmp to compare the parts[0] string to "$GPRMC". That is:

 

if (strcmp(parts[0], "$GPRMC")) {
    /// strings are not identical
    ...
}

 

And yeah, make sure the pointer array is allocated...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Most "parts" of a nmea string are already separated by commas, so you can use scanf() to place these "parts" into string arrays.

Then just compare the parsed strings to what you are interested in.

I recently put together a clock project that uses an adafruit gps module so the clock sets itself from the nmea time stamp.

Adafruit has an Arduino sketch for parsing the gps data, you may want to look at it and copy what is useful for your project.

Or at least look at how they did it.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your solutions. I have tried to use strcmp() to compare the strings and it works. Previously I tried using memcmp(), but that didn't work for some reason.

 

I am not sure however how to allocate storage to the pointer array and what that actually does.

I suppose I should also implement a check to see if there are too many commas in the string so that it doesn't overflow something?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You haven't allocated any storage for the 15 pointers in the parts[] array?

char *parts[15];

 

huh?  Looks like 15 pointers are allocated to me.

The code leaves the tokens "in place" in the original NMEA string, replaces their comma separators with nulls, and sticks pointers to each token in the part array.

 

If you had started with:

char test_string[] = "$GPRMC,161229.487,A,3723.2475,N,12158.3416,W,CHKSUM";
char *parts[15];  //uninitialized

You would end up with (where each "o" represents a '\0' character:

// columns:           0123456789 123456789 123456789 123456789 123456789
char test_string[] = "$GPRMCo161229.487oAo3723.2475oNo12158.3416oWoCHKSUM";
char *parts[15] = { &test_string[0],
  &test_string[7],
  &test_string[18],
  &test_string[20],
  &test_string[30],
  &test_string[32],
  &test_string[43],
  &test_string[45],
   :