鱼C论坛

 找回密码
 立即注册
查看: 2697|回复: 10

[已解决]C语言:关于GPS数据处理

[复制链接]
发表于 2017-5-7 19:46:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
各位大佬帮忙瞅瞅,才输入完程序就崩溃了!!!
#include <stdio.h>
#include <string.h>

int isJYZ(int n);      //判断校验是否正确 
void BJT(int UTC);     //将UTC时间换成北京时间 

int main()
{
        char s[127],s1[127],a[127],b[127];
        //scanf("%s\n",&s);
        //strcpy(s1,s);
        int i1,i2 = 0,sum = 0;
        int length1,length2;
        //length1 = sizeof(s);
        length1 = 0;
        do{
                scanf("%s",&s);
                strcat(s1,s);
                length1 += sizeof(s);
        }while(strcmp(s,'END') != 0);
        
        while(1){
                strrchr(a,strrchr(s1,'));
                length2 = sizeof(a);
                sum += length2;
                for( i1=0 ; i1< length2 ; i1++ ){
                        if(i2 < 16){
                                b[i2] = a[i1];
                        }else{
                                if(i1 >= length2-2) b[i2] = a[i1];
                        }
                        
                        if(a[i1] =  ','){
                                i2++;
                        } 
                }
                if(b[2]=='A' && isJYZ(b[16])){
                        BJT(b[1]);
                        break;
                }
                for( i1=0 ; i1<length1-sum ; i1++ ){
                        s1[i1] = s[i1];
                }
        }
        
        return 0;
}

int isJYZ(int n)
{
        int i = 0;   //校验不正确 
        int a,b;
        a = b/10;
        int y = 1;
        while(a < b%10){
                y ^= a;
                a++;
        }
        if(y%65536 == n){
                i = 1;   //校验正确 
        }
        return i; 
}

void BJT(int UTC){
        int a1,a2,b,c;
        a1 = UTC/10000;
        b = UTC%10000/100;
        c = UTC%10000%100;
        if(a1 >= 1 && a1 <= 16){
                a2 = a1 + 8;
        }else{
                a2 = a1 + 8 - 24;
        }
        if(a2 < 10){
                printf("0%d",a2);
        }else{
                printf("%d",a2);
        }
        if(b < 10){
                printf("0%d",b);
        }else{
                printf("%d",b);
        }
        if(c < 10){
                printf("0%d",c);
        }else{
                printf("%d",c);
        }
}
最佳答案
2017-5-8 17:12:57
本帖最后由 超凡天赐 于 2017-5-8 17:15 编辑

好吧,这一题我已经帮你做出来了,你写的代码我看不懂, 所以我就自己写了一个。
其实这一题一点也不难,要放到竞赛,真是比送分还送分。就是题目有点长。这么长的题目,我们给它浓缩一下:
先验证‘$’和‘*’之间的字符累异或后的值(其实和累乘一个道理)是否等于‘*’后的两位数(这个数是16位进制的);
然后再将第一个逗号后的UCT时间转化为北京时间(其实就是将逗号后的两个数加上8,如果大于24就要剪去24;如果小于10,前面就要补零,比如02)。
当然了上面的只不过是我们的猜想,还要验证一下。写一个小代码
#include <stdio.h>
#include <string.h>
int main()
{
    char a[100];
    scanf("%s",a);
    long length;
    length=strlen(a);
    int i;
    int product=0;
    for(i=0;i<length;i++)
        product^=a[i];
    int result;
    result=product%65536;
    printf("%x",result);
}//GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A
我们输入一下题目中所给的数据
GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A
输出的结果为
50
对了,好这下我们要用代码来描绘算法了。
#include <stdio.h>
#include <string.h>
int verification(char str[])
{
    int a,b;
    int location=0;
    while(str[location]!='*')
    {
        location++;
    }
    if(str[location+1]>='A'&&str[location+1]<='F')
        a=str[location+1]-'A'+10;
    else
        a=str[location+1]-'0';
    if(str[location+2]>='A'&&str[location+2]<='F')
        b=str[location+2]-'A'+10;
    else
        b=str[location+2]-'0';
    int proof_text_value;
    proof_text_value=a*16+b;//proof_text_value转化为10进制数

    int product=0,i;
    for(i=1;i<=location-1;i++)
        product^=str[i];
    product=product%65536;//product为10进制数
    if(product==proof_text_value)
        return 1;
    else
        return 0;
}
void transfer_time(char str[])//只需要对location+1到location+2位数字进行转换
{
    int a,b;
    int location=0;
    while(str[location]!=',')
    {
        location++;
    }
    a=str[location+1]-'0';
    b=str[location+2]-'0';
    int UCT_time,Beijing_time;
    UCT_time=a*10+b;
    Beijing_time=UCT_time+8;
    if(Beijing_time>=24)
        printf("%d:%c%c:%c%c\n",Beijing_time-24,str[location+3],str[location+4],str[location+5],str[location+6]);
    else if(Beijing_time<10)
        printf("0%d:%c%c:%c%c\n",Beijing_time,str[location+3],str[location+4],str[location+5],str[location+6]);
    else
        printf("%d:%c%c:%c%c\n",Beijing_time,str[location+3],str[location+4],str[location+5],str[location+6]);
}
int main()
{
    char a[100][100];
    char b[10]="END";
    int i=0,n;
    do
    {
        scanf("%s",a[i]);
        i++;
    }while(strcmp(a[i-1],b)!=0);
    for(n=0;n<i-1;n++)
        if(verification(a[n])==1)
            transfer_time(a[n]);
    return 0;
}
我们下面要输入数据,老天保佑不要错
$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
END
对了对了
10:48:13
ok,但是我还要提醒你, ,在竞赛中,那群变态会找一大些数据来测试,一个不通过抠分。超时也会扣分,甚至0分。所以这个代码有可能不会得100
不过这个题目有一点我不明白,那就是我一开始认为这个字符数组长度是固定的。因为好像每一项都是固定的。不过后来我看到他的题目说长度是不固定的。所以一开始我的代码是
#include <stdio.h>
#include <string.h>
int main()
{
    char a[100];
    scanf("%s",a);
    long length;
    length=strlen(a);
    int i;
    int product=0;
    for(i=0;i<length;i++)
        product^=a[i];
    int result;
    result=product%65536;
    printf("%x",result);
}//GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A

//其实依据你这道题的意思,刚开始时,字符长度已经确定了,为71。
#include <stdio.h>
#include <string.h>
int verification(char str[])
{
    int a,b;
    if(str[69]>='A'&&str[69]<='F')
        a=str[69]-'A'+10;
    else
        a=str[69]-'0';
    if(str[69]>='A'&&str[69]<='F')
        b=str[70]-'A'+10;
    else
        b=str[70]-'0';
    int proof_text_value;
    proof_text_value=a*16+b;//proof_text_value转化为10进制数

    int product=0,i;
    for(i=1;i<=67;i++)
        product^=str[i];
    product=product%65536;//product为10进制数
    if(product==proof_text_value)
        return 1;
    else
        return 0;
}
void transfer_time(char str[])//只需要对7到8位数字进行转换
{
    int a,b;
    a=str[7]-'0';
    b=str[8]-'0';
    int UCT_time,Beijing_time;
    UCT_time=a*10+b;
    Beijing_time=UCT_time+8;
    if(Beijing_time>=24)
        printf("%d:%c%c:%c%c\n",Beijing_time-24,str[9],str[10],str[11],str[12]);
    else if(Beijing_time<10)
        printf("0%d:%c%c:%c%c\n",Beijing_time,str[9],str[10],str[11],str[12]);
    else
        printf("%d:%c%c:%c%c\n",Beijing_time,str[9],str[10],str[11],str[12]);
}
int main()
{
    char a[100][100];
    char b[10]="END";
    int i=0,n;
    do
    {
        scanf("%s",a[i]);
        i++;
    }while(strcmp(a[i-1],b)!=0);
    for(n=0;n<i;n++)
        if(verification(a[n])==1)
            transfer_time(a[n]);
    return 0;
}
有点啰嗦,但我希望你能看完。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-5-7 20:18:01 | 显示全部楼层
本帖最后由 超凡天赐 于 2017-5-7 20:20 编辑
#include <stdio.h>
#include <string.h>

int isJYZ(int n);      //判断校验是否正确
void BJT(int UTC);     //将UTC时间换成北京时间
void BJT(int UTC)
{
    int a1,a2,b,c;
    a1 = UTC/10000;
    b = UTC%10000/100;
    c = UTC%10000%100;
    if(a1 >= 1 && a1 <= 16)
    {
        a2 = a1 + 8;
    }
    else
    {
        a2 = a1 + 8 - 24;
    }
    if(a2 < 10)
    {
        printf("0%d",a2);
    }
    else
    {
        printf("%d",a2);
    }
    if(b < 10)
    {
        printf("0%d",b);
    }
    else
    {
        printf("%d",b);
    }
    if(c < 10)
    {
        printf("0%d",c);
    }
    else
    {
        printf("%d",c);
    }
}
int isJYZ(int n)
{
    int i = 0;   //校验不正确
    int a,b = 0;
    a = b/10;
    int y = 1;
    while(a < b%10)
    {
        y ^= a;
        a++;
    }
    if(y%65536 == n)
    {
        i = 1;   //校验正确
    }
    return i;
}
int main()
{
    char s[127],s1[127],a[127],b[127];
    //scanf("%s\n",s);
    //strcpy(s1,s);
    int i1,i2 = 0,sum = 0;
    int length1,length2;
    //length1 = sizeof(s);
    length1 = 0;
    do
    {
        scanf("%s",s);
        strcat(s1,s);
        length1 += sizeof(s);
    }while(strcmp(s,"END") != 0);
    
    while(1)
    {
        strrchr(a,*strrchr(s1,'a'));
        length2 = sizeof(a);
        sum += length2;
        for( i1=0 ; i1< length2 ; i1++ )
        {
            if(i2 < 16)
            {
                b[i2] = a[i1];
            }
            else
            {
                if(i1 >= length2-2) b[i2] = a[i1];
            }
            if(a[i1] ==  ',')
            {
                i2++;
            }
            if(b[2]=='A' && isJYZ(b[16]))
            {
                BJT(b[1]);
                break;
            }
            for( i1=0 ; i1<length1-sum ; i1++ )
            {
                s1[i1] = s[i1];
            }
        }
    }
    return 0;
}
你的代码错的太多了,我找了一些错误。比如strchr()函数返回的是地址,应加上“*”。
scanf("%s",&s);
明显的错误应改为
scanf("%s",s);
等等一些错误,还有你的代码缩进非常糟糕。至于你有没有逻辑错误,你没给题目,我也不知道
如果你发现上述代码不能运行成功,请讲清楚题目。代码也没有给输入提示。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-7 20:47:04 | 显示全部楼层

题目内容:
NMEA-0183协议是为了在不同的GPS(全球定位系统)导航设备中建立统一的BTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The National Marine Electronics Associa-tion)制定的一套通讯协议。GPS接收机根据NMEA-0183协议的标准规范,将位置、速度等信息通过串口传送到PC机、PDA等设备。

NMEA-0183协议是GPS接收机应当遵守的标准协议,也是目前GPS接收机上使用最广泛的协议,大多数常见的GPS接收机、GPS数据处理软件、导航软件都遵守或者至少兼容这个协议。

NMEA-0183协议定义的语句非常多,但是常用的或者说兼容性最广的语句只有$GPGGA、$GPGSA、$GPGSV、$GPRMC、$GPVTG、$GPGLL等。

其中$GPRMC语句的格式如下:
    $GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50

这里整条语句是一个文本行,行中以逗号“,”隔开各个字段,每个字段的大小(长度)不一,这里的示例只是一种可能,并不能认为字段的大小就如上述例句一样。
    字段0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐最小定位信息
    字段1:UTC时间,hhmmss.sss格式
    字段2:状态,A=定位,V=未定位
    字段3:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
    字段4:纬度N(北纬)或S(南纬)
    字段5:经度dddmm.mmmm,度分格式(前导位数不足则补0)
    字段6:经度E(东经)或W(西经)
    字段7:速度,节,Knots
    字段8:方位角,度
    字段9:UTC日期,DDMMYY格式
    字段10:磁偏角,(000 - 180)度(前导位数不足则补0)
    字段11:磁偏角方向,E=东W=西
    字段16:校验值
这里,“*”为校验和识别符,其后面的两位数为校验和,代表了“$”和“*”之间所有字符(不包括这两个字符)的异或值的十六进制值。上面这条例句的校验和是十六进制的50,也就是十进制的80。

提示:^运算符的作用是异或。将$和*之间所有的字符做^运算(第一个字符和第二个字符异或,结果再和第三个字符异或,依此类推)之后的值对65536取余后的结果,应该和*后面的两个十六进制数字的值相等,否则的话说明这条语句在传输中发生了错误。注意这个十六进制值中是会出现A-F的大写字母的。

现在,你的程序要读入一系列GPS输出,其中包含$GPRMC,也包含其他语句。在数据的最后,有一行单独的
    END
表示数据的结束。

你的程序要从中找出$GPRMC语句,计算校验和,找出其中校验正确,并且字段2表示已定位的语句,从中计算出时间,换算成北京时间。一次数据中会包含多条$GPRMC语句,以最后一条语句得到的北京时间作为结果输出。
你的程序一定会读到一条有效的$GPRMC语句。

输入格式:
多条GPS语句,每条均以回车换行结束。最后一行是END三个大写字母。

输出格式:
6位数时间,表达为:
    hh:mm:ss
其中,hh是两位数的小时,不足两位时前面补0;mm是两位数的分钟,不足两位时前面补0;ss是两位数的秒,不足两位时前面补0。

输入样例:
$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
END

输出样例:
10:48:13
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-7 20:51:11 | 显示全部楼层
超凡天赐 发表于 2017-5-7 20:18
你的代码错的太多了,我找了一些错误。比如strchr()函数返回的是地址,应加上“*”。

明显的错误应 ...

为什么 scanf("%s",s); 不用&???
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-7 22:11:40 | 显示全部楼层
星若有泪 发表于 2017-5-7 20:51
为什么 scanf("%s",s); 不用&???

s本身表示的就是一个地址,是字符数组的首地址。&s是什么鬼
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-7 22:12:16 | 显示全部楼层
星若有泪 发表于 2017-5-7 20:47
题目内容:
NMEA-0183协议是为了在不同的GPS(全球定位系统)导航设备中 ...


你这是竞赛题吧,这么长?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-7 22:30:02 | 显示全部楼层
超凡天赐 发表于 2017-5-7 22:12
你这是竞赛题吧,这么长?

我也不知道啊  我在一个软件上学c  人家给的题。。。所以说 我的程序问题很大吗
我主要就是想知道 关于字符串的输入问题 能不能讲讲先
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-8 08:58:11 | 显示全部楼层
星若有泪 发表于 2017-5-7 22:30
我也不知道啊  我在一个软件上学c  人家给的题。。。所以说 我的程序问题很大吗
我主要就是想知道 关于 ...

s本身表示的就是一个地址,是字符数组的首地址。&s是什么鬼
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-8 17:12:57 | 显示全部楼层    本楼为最佳答案   
本帖最后由 超凡天赐 于 2017-5-8 17:15 编辑

好吧,这一题我已经帮你做出来了,你写的代码我看不懂, 所以我就自己写了一个。
其实这一题一点也不难,要放到竞赛,真是比送分还送分。就是题目有点长。这么长的题目,我们给它浓缩一下:
先验证‘$’和‘*’之间的字符累异或后的值(其实和累乘一个道理)是否等于‘*’后的两位数(这个数是16位进制的);
然后再将第一个逗号后的UCT时间转化为北京时间(其实就是将逗号后的两个数加上8,如果大于24就要剪去24;如果小于10,前面就要补零,比如02)。
当然了上面的只不过是我们的猜想,还要验证一下。写一个小代码
#include <stdio.h>
#include <string.h>
int main()
{
    char a[100];
    scanf("%s",a);
    long length;
    length=strlen(a);
    int i;
    int product=0;
    for(i=0;i<length;i++)
        product^=a[i];
    int result;
    result=product%65536;
    printf("%x",result);
}//GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A
我们输入一下题目中所给的数据
GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A
输出的结果为
50
对了,好这下我们要用代码来描绘算法了。
#include <stdio.h>
#include <string.h>
int verification(char str[])
{
    int a,b;
    int location=0;
    while(str[location]!='*')
    {
        location++;
    }
    if(str[location+1]>='A'&&str[location+1]<='F')
        a=str[location+1]-'A'+10;
    else
        a=str[location+1]-'0';
    if(str[location+2]>='A'&&str[location+2]<='F')
        b=str[location+2]-'A'+10;
    else
        b=str[location+2]-'0';
    int proof_text_value;
    proof_text_value=a*16+b;//proof_text_value转化为10进制数

    int product=0,i;
    for(i=1;i<=location-1;i++)
        product^=str[i];
    product=product%65536;//product为10进制数
    if(product==proof_text_value)
        return 1;
    else
        return 0;
}
void transfer_time(char str[])//只需要对location+1到location+2位数字进行转换
{
    int a,b;
    int location=0;
    while(str[location]!=',')
    {
        location++;
    }
    a=str[location+1]-'0';
    b=str[location+2]-'0';
    int UCT_time,Beijing_time;
    UCT_time=a*10+b;
    Beijing_time=UCT_time+8;
    if(Beijing_time>=24)
        printf("%d:%c%c:%c%c\n",Beijing_time-24,str[location+3],str[location+4],str[location+5],str[location+6]);
    else if(Beijing_time<10)
        printf("0%d:%c%c:%c%c\n",Beijing_time,str[location+3],str[location+4],str[location+5],str[location+6]);
    else
        printf("%d:%c%c:%c%c\n",Beijing_time,str[location+3],str[location+4],str[location+5],str[location+6]);
}
int main()
{
    char a[100][100];
    char b[10]="END";
    int i=0,n;
    do
    {
        scanf("%s",a[i]);
        i++;
    }while(strcmp(a[i-1],b)!=0);
    for(n=0;n<i-1;n++)
        if(verification(a[n])==1)
            transfer_time(a[n]);
    return 0;
}
我们下面要输入数据,老天保佑不要错
$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
END
对了对了
10:48:13
ok,但是我还要提醒你, ,在竞赛中,那群变态会找一大些数据来测试,一个不通过抠分。超时也会扣分,甚至0分。所以这个代码有可能不会得100
不过这个题目有一点我不明白,那就是我一开始认为这个字符数组长度是固定的。因为好像每一项都是固定的。不过后来我看到他的题目说长度是不固定的。所以一开始我的代码是
#include <stdio.h>
#include <string.h>
int main()
{
    char a[100];
    scanf("%s",a);
    long length;
    length=strlen(a);
    int i;
    int product=0;
    for(i=0;i<length;i++)
        product^=a[i];
    int result;
    result=product%65536;
    printf("%x",result);
}//GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A

//其实依据你这道题的意思,刚开始时,字符长度已经确定了,为71。
#include <stdio.h>
#include <string.h>
int verification(char str[])
{
    int a,b;
    if(str[69]>='A'&&str[69]<='F')
        a=str[69]-'A'+10;
    else
        a=str[69]-'0';
    if(str[69]>='A'&&str[69]<='F')
        b=str[70]-'A'+10;
    else
        b=str[70]-'0';
    int proof_text_value;
    proof_text_value=a*16+b;//proof_text_value转化为10进制数

    int product=0,i;
    for(i=1;i<=67;i++)
        product^=str[i];
    product=product%65536;//product为10进制数
    if(product==proof_text_value)
        return 1;
    else
        return 0;
}
void transfer_time(char str[])//只需要对7到8位数字进行转换
{
    int a,b;
    a=str[7]-'0';
    b=str[8]-'0';
    int UCT_time,Beijing_time;
    UCT_time=a*10+b;
    Beijing_time=UCT_time+8;
    if(Beijing_time>=24)
        printf("%d:%c%c:%c%c\n",Beijing_time-24,str[9],str[10],str[11],str[12]);
    else if(Beijing_time<10)
        printf("0%d:%c%c:%c%c\n",Beijing_time,str[9],str[10],str[11],str[12]);
    else
        printf("%d:%c%c:%c%c\n",Beijing_time,str[9],str[10],str[11],str[12]);
}
int main()
{
    char a[100][100];
    char b[10]="END";
    int i=0,n;
    do
    {
        scanf("%s",a[i]);
        i++;
    }while(strcmp(a[i-1],b)!=0);
    for(n=0;n<i;n++)
        if(verification(a[n])==1)
            transfer_time(a[n]);
    return 0;
}
有点啰嗦,但我希望你能看完。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-11 14:42:07 | 显示全部楼层
超凡天赐 发表于 2017-5-8 17:12
好吧,这一题我已经帮你做出来了,你写的代码我看不懂, 所以我就自己写了一个。
其实这一题一 ...

为什么我答得这么详细,也不给采纳?@人造人

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +5 收起 理由
人造人 + 5 + 5 + 5 ^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2017-5-11 15:00:34 | 显示全部楼层
看下学习学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-28 06:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表