Weird sscanf behavior

So I’m attempting to parse this GPS string:

$GPRMC,024019.875,A,3326.2163,N,11145.6687,W,000.0,184.4,211013,,,A*7C

Here is my code:

typedef struct __attribute__((packed)) {
  utime unixtime;
  float lat;
  boolean is_lat_N;
  float lon;
  boolean is_lon_E;
  byte day;
  byte month;
  unsigned short year;
} GPS_Coords;
[...]
 GPS_Coords coords;
 char lat_c, lon_c;
 unsigned char hours;
 unsigned char minutes;
 unsigned char seconds;

 sscanf(data, "$GPRMC,%2hhu%2hhu%2hhu%*4s,%*1c,%4f%*5s,%1c,%4f%*6s,%1c,%*f,%*f,%2hhu%2hhu%2hu,%*s", &hours, &minutes, &seconds, &coords.lat, &lat_c, &coords.lon, &lon_c, &coords.day, &coords.month, &coords.year);

Now when I run this code on the C++ compiler on ideone.com it works as expected and I get the right output. But for some reason when I run it on my Mega it chokes and gives me 0.0 for latitude. Any ideas?

By default, the avr-libc implementations of printf/scanf do not support floats. You have to change the compile/link command to bring in the bigger stdio library.

Alright I tried linking in the proper library and this code runs perfectly:

#include <Arduino.h>

typedef struct
	__attribute__((packed)) {
		int unixtime;
		float lat;
		unsigned char is_lat_N;
		float lon;
		unsigned char is_lon_E;
		unsigned char day;
		unsigned char month;
		unsigned short year;
	} GPS_Coords;

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

// the loop routine runs over and over again forever:
	void loop() {
		GPS_Coords coords;
		char lat_c, lon_c;
		unsigned char hours;
		unsigned char minutes;
		unsigned char seconds;
		char buff[] =
				"$GPRMC,024019.875,A,3326.2163,N,11145.6687,W,000.0,184.4,211013,,,A*7C\r\n                ";

		sscanf(buff,
				"$GPRMC,%2hhu%2hhu%2hhu%*4s,%*1c,%6f%*3s,%1c,%7f%*3s,%1c,%*f,%*f,%2hhu%2hhu%2hu,%*s",
				&hours, &minutes, &seconds, &coords.lat, &lat_c, &coords.lon,
				&lon_c, &coords.day, &coords.month, &coords.year);
		Serial.print("lat:");
		Serial.print(coords.lat);
		Serial.println(lat_c);
		Serial.print("lon:");
		Serial.print(coords.lon);
		Serial.println(lon_c);
		Serial.print("month:");
		Serial.println(coords.month);
		Serial.print("day:");
		Serial.println(coords.day);
		Serial.print("year:");
		Serial.println(coords.year);
	}

However, the code in my application still gives me the wrong results:

GPS_Coords GPS::get_coords() {
	GPS_Coords coords;
	char lat_c, lon_c;
	unsigned char hours;
	unsigned char minutes;
	unsigned char seconds;
	char buff[100];
	int count = 0;
	while (true) {
		char byteGPS = -1;
		byteGPS = gpsSerial.read();
		if (byteGPS == -1) {
			delay(5);
		} else {
			buff[count] = byteGPS;
			count++;
			if (byteGPS == 13) { //Reached end of data
				buff[count-1] = '\0';
				count = 0;

				//check if we have found the proper GPS command.
				if (strstr(buff, "$GPRMC") != 0) {

					Serial.println(buff);
					//parse the coordinates	GPS_Coords coords;

					//Parse data
					sscanf(buff,
							"$GPRMC,%2hhu%2hhu%2hhu%*4s,%*1c,%6f%*3s,%1c,%7f%*3s,%1c,%*f,%*f,%2hhu%2hhu%2hu,%*s",
							&hours, &minutes, &seconds, &coords.lat, &lat_c, &coords.lon,
							&lon_c, &coords.day, &coords.month, &coords.year);
					coords.year += 2000;
					Serial.print("lat:");
					Serial.print(coords.lat);
					Serial.println(lat_c);
					Serial.print("lon:");
					Serial.print(coords.lon);
					Serial.println(lon_c);
					Serial.print("month:");
					Serial.println(coords.month);
					Serial.print("day:");
					Serial.println(coords.day);
					Serial.print("year:");
					Serial.println(coords.year);
					memset(buff, 0, sizeof(buff));
					break;
				}
				memset(buff, 0, sizeof(buff));
			}
		}
	}
	return coords;
}

I get this output:

lat:ovf-
lon:0.00
month:0
day:0
year:4560

I figured it out, there was a character at the beginning of the string screwing it up, I just changed the following:

sscanf(buffzor,
								"%*1c$GPRMC,%2hhu%2hhu%2hhu%*4s,%*1c,%6f%*3s,%1c,%7f%*3s,%1c,%*f,%*f,%2hhu%2hhu%2hu,%*s",
								&hours, &minutes, &seconds, &coords.lat, &lat_c,
								&coords.lon, &lon_c, &coords.day, &coords.month,
								&coords.year);