利用strstr和sscanf解析GPS信息

转自:http://www.cnblogs.com/shenlian/archive/2011/10/10/2205884.html


利用strstr和sscanf解析GPS信息

考察C程序员是否合格的一个重要标准就是看他操作字符串的能力,一个合格的C程序员应该可以熟练的对字符串进行拆分、组合、格式转换以及搜索定位,从一堆数据中提取出有效信息。 比如说我们要做一个GPS导航的项目,需要读取GPS模块以ASCII码的形式发送过来的数据,然后对这些数据进行处理,提取我们需要的信息。这就涉及到很多操作字符串的问题。

下面就以此为例,利用strstr函数和sscanf函数解析GPS数据。

GPS输出的数据格式如下: $GPGGA,121252.000,3937.3032,N,11611.6046,E,1,05,2.0,45.9,M,-5.7,M,,0000*77 $GPRMC,121252.000,A,3958.3032,N,11629.6046,E,15.15,359.95,070306,,,A*54 $GPVTG,359.95,T,,M,15.15,N,28.0,K,A*04 $GPGGA,121253.000,3937.3090,N,11611.6057,E,1,06,1.2,44.6,M,-5.7,M,,0000*72 $GPGSA,A,3,14,15,05,22,18,26,,,,,,,2.1,1.2,1.7*3D $GPGSV,3,1,10,18,84,067,23,09,67,067,27,22,49,312,28,15,47,231,30*70 $GPGSV,3,2,10,21,32,199,23,14,25,272,24,05,21,140,32,26,14,070,20*7E $GPGSV,3,3,10,29,07,074,,30,07,163,28*7D

可以看到,GPS模块发送过来的原始数据有很多,但是通常我们只需要其中的一部分信息就够用了,比如对于导航的功能,我们只需要以$GPRMC开头,以换行符结束的一行信息就够了。

即: $GPRMC,121252.000,A,3958.3032,N,11629.6046,E,15.15,359.95,070306,,,A*54 因此我们需要做的就是从读取的数据中截取以$GPRMC开头的一行信息,然后从中解析出经纬度、日期时间等有效信息即可。

假设从串口读取的数据存放在一个字符串指针char *raw_buf指向的内存单元里,首先我们通过ANSI C提供的strstr()函数找到以$GPRMC开头以换行符’\n’结束的字符串:

/* find "$GPRMC" from raw_buf */

if ((wellhandled_string = strstr(raw_buf, “$GPRMC”)) != NULL)

{ for (i=0; i,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh

<1> UTC时间,hhmmss(时分秒)格式

<2> 定位状态,A=有效定位,V=无效定位

<3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)

<4> 纬度半球N(北半球)或S(南半球)

<5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)

<6> 经度半球E(东经)或W(西经)

<7> 地面速率(000.0~999.9节,前面的0也将被传输)

<8> 地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)

<9> UTC日期,ddmmyy(日月年)格式

<10> 磁偏角(000.0~180.0度,前面的0也将被传输)

<11> 磁偏角方向,E(东)或W(西)

<12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效) 我们提取1~9九条信息。

$GPRMC ,121252.000 ,A ,3958.3032 ,N ,11629.6046 ,E ,15.15 ,359.95 ,070306, , ,A*54

用一个结构体存放这些信息: typedef struct gps_info

              { char utc_time[BUF_SIZE];

               char status;

               float latitude_value;

               char latitude;

            float longtitude_value;

               char longtitude;

              float speed;

               float azimuth_angle;

              char utc_data[BUF_SIZE];

             }GPS_INFO;

因为每一个字段之间都是以逗号间隔开的,所以我们可以利用%[^,]来分割字符串,这样用sscanf函数就可以实现对有效信息的提取:

sscanf(wellhandled_string,

"$GPRMC,%[^,],%c,%f,%c,%f,%c,%f,%f,%[^,]",

rmc_info->utc_time,

    &(rmc_info->status),

    &(rmc_info->latitude_value),

    &(rmc_info->latitude),

    &(rmc_info->longtitude_value),

    &(rmc_info->longtitude),

    &(rmc_info->speed),

    &(rmc_info->azimuth_angle),

    rmc_info->utc_data )

; 这个函数执行后,打印出的保存在struct gps_info结构体里的信息如下所示:

utc_time: 024813.640

status: A

latitude: N

latitude value: 3158.460693 longtitude: E

longtitude value: 11848.374023

speed: 10.050000

azimuth_angle: 324.269989

utc_data: 150706

可见,利用好sscanf函数,可以让我们可以很高效的处理字符串。



备注:

strstr:

包含文件:string.h
函数名: strstr   
函数原型:extern char *strstr(char *str1, char *str2);   
功能:找出str2字符串在str1字符串中第一次出现的位置(不包括str2的串结束符)。   
返回值:返回该位置的指针,如找不到,返回空指针。


sscanf:

sscanf() - 从一个字符串中读进与指定格式相符的数据.   
函数原型:   
int sscanf( const char *, const char *, ...);   
int sscanf(const char *buffer,const char *format,[argument ]...);   
buffer 存储的数据   
format 格式控制字符串   
argument 选择性设定字符串 
  
sscanf会从buffer里读进数据,依照argument的设定将数据写回。

strchr

原型:extern char *strchr(const char *s,char c);   
const char *strchr(const char* _Str,int _Val)   
char *strchr(char* _Str,int _Ch)   
头文件:#include <string.h>   
功能:查找字符串s中首次出现字符c的位置   
说明:返回首次出现c的位置的指针,如果s中不存在c则返回NULL。   
返回值:Returns the address of the first occurrence of the character in the string if successful, or NULL otherwise



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值