《编程思维与实践》1049.GPS数据处理
题目
思路
注记: UTC为世界标准时间(0时区),东区加,西区减.
分两步实现:
1.判断是否为有效的语句:
有效需要满足三个条件:
①语句含$GPRMC,可以通过strstr搜索来判断;
②状态已定位,可以用sscanf来读取判断;
③异或结果与校验值相同,校验值的读取可以用提示中的sscanf.
2.求出北京时间,直接从字段1中就可读取,只需要将小时数+8(东八区)后模24即可(保证不超过24);
其中,如果有多个语句有效,则输出最后一个语句的结果(通过覆盖容易实现).
以下为sscanf的简单介绍:
sscanf的使用方式与scanf类似,%*表示跳过该内容,
集合操作: %[ 匹配内容 ] 满足贪婪性:连续读取满足要求的内容,不满足要求就停止读入不再处理后续内容.
%[a-z1-9]表示读取字符串中满足1-9或者a-z的内容(如下图);
%[ ^ , ]表示读取字符串非逗号的内容;如果需要跳过某个字符只需要在格式化中输入这个字符即可,如: %*[ ^ ,], 就表示跳过逗号前的字符串和逗号.
注意的点:
1.数据中时间秒数的小数点后不一定是三位,所以读取定位状态时应该以第二个逗号为分界点而不是字符个数.
2.小时数如果是用整数输出则有可能不足两位,需要补前置0,格式化输出时%02d即可.
也可参考以下的分析:
代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 65536
int main()
{
char s[1000];
char h[3],min[3],sec[3]; //hour minute second
int hour;
while(scanf("%s",s)&&strcmp(s,"END")!=0)
{
char state; //记录状态是否定位
sscanf(s,"%*[^,],%*[^,],%c",&state); //跳过两个逗号
if(strstr(s,"$GPRMC")!=NULL&&state=='A')
{
int judge=s[1]; //异或结果
for(int i=2;s[i]!='*';i++)
{
judge^=s[i];
}
judge%=N;
int check; //校验值
sscanf(s,"%*[^*]*%x",&check); //跳过* 读取十六进制的校验值
if(judge==check) //校验成功
{
h[0]=s[7];
h[1]=s[8];
h[2]='\0';
min[0]=s[9];
min[1]=s[10];
min[2]='\0';
sec[0]=s[11];
sec[1]=s[12];
sec[2]='\0';
hour=(atoi(h)+8)%24; //东八区
}
}
}
printf("%02d:%s:%s\n",hour,min,sec); //02d表示不足2位前补0
return 0;
}