首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >用C语言中的strok解析NMEA字符串

用C语言中的strok解析NMEA字符串
EN

Stack Overflow用户
提问于 2018-01-28 05:37:58
回答 2查看 3.5K关注 0票数 0

我正试图使用带有分隔符的strtok函数来解析一个GNRMC字符串,",当我注意到一些我没有预料到的不同的事情时,一切都进行得很顺利。如果字符串包含连续的","然后strtok超调和打印函数错误地放置真实的数据,我的目标是打印数字当在连续的之间没有可用的数据“,"

我该怎么做呢?

这是我的密码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
 char str[] = "$GPRMC,105954.000,A,3150.6731,N,11711.9399,E,0.00,96.10,250313,,,A*53";
 char* Message_ID = strtok(str,",");
 char* Time = strtok(NULL,",");
 char* Data_Valid = strtok(NULL,",");
 char* Raw_Latitude = strtok(NULL,",");
 char* N_S = strtok(NULL,",");
 char* Raw_Longitude = strtok(NULL,",");
 char* E_W = strtok(NULL,",");
 char* Speed = strtok(NULL,",");
 char* COG = strtok(NULL,",");
 char* Date = strtok(NULL,",");
 char* Magnetic_Variation = strtok(NULL,",");
 char* M_E_W = strtok(NULL,",");
 char* Positioning_Mode = strtok(NULL,",");

 double Latitude = atof(Raw_Latitude);
 double Longitude = atof(Raw_Longitude);

  printf("The Message ID is : %s\n", Message_ID);
  printf("The Time is : %s\n", Time);
  printf("The data valid is : %s\n", Data_Valid);
  printf("The Latitude is : %f\n", Latitude);
  printf("The N_S is : %s\n", N_S);
  printf("The Longitude is : %f\n", Longitude);
  printf("The E_W is : %s\n", E_W);
  printf("The Speed is : %s\n", Speed);
  printf("The COG is : %s\n", COG);
  printf("The Date is : %s\n", Date);
  printf("The Magnetic_Variation is : %s\n", Magnetic_Variation);
  printf("The M_E_W is : %s\n", M_E_W);
  printf("The Positioning_Mode is : %s\n", Positioning_Mode);

    return 0;
}

输出窗口

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-28 06:26:17

如果您只检测到一个特定的字符(如','),那么直接前进的方法将是使用好的旧strchr()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 char str[] = 
   "$GPRMC,105954.000,A,3150.6731,N,11711.9399,E,0.00,96.10,250313,,,A*53";

 char* message_id = str;

 char* time = strchr(message_id, ','); *time = '\0'; ++time;
 char* data_valid = strchr(time,","); *data_valid = '\0'; ++data_valid;
 char* raw_latitude = strchr(data_valid,","); *raw_latitude = '\0'; ++raw_latitude;
 ...

一个复杂的宏可以简化使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define FIND_AND_NUL(s, p, c) ( \
   (p) = strchr(s, c), \
   *(p) = '\0', \
   ++(p), \
   (p))

像这样使用它:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 char str[] = 
   "$GPRMC,105954.000,A,3150.6731,N,11711.9399,E,0.00,96.10,250313,,,A*53";

 char* message_id = str;

 char* time = FIND_AND_NUL(message_id, time, ',');
 char* data_valid = FIND_AND_NUL(time, data_valid, ',');
 char* raw_latitude = FIND_AND_NUL(data_valid, raw_latitude, ',');
 ...
票数 3
EN

Stack Overflow用户

发布于 2020-01-25 16:46:34

我使用我自己的strtok函数,它非常简单,但与原始函数有两个不同之处:(1)分隔符只是一个字符,而不是字符串(2)如果要解析的字符串有两个连续的分隔符,则该函数返回一个空的非空标记“。这对于解析NMEA消息非常方便。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
char *strtok_fr (char *s, char delim, char **save_ptr)
{
    char *tail;
    char c;

    if (s == NULL) {
        s = *save_ptr;
    }
    tail = s;
    if ((c = *tail) == '\0') {
        s = NULL;
    }
    else {
        do {
            if (c == delim) {
                *tail++ = '\0';
                break;
           }
        }while ((c = *++tail) != '\0');
    }
    *save_ptr = tail;
    return s;
}

非递归版本:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
char *strtok_f (char *s, char delim)
{
    static char *save_ptr;

    return strtok_fr (s, delim, &save_ptr);
}

因此,您的示例(注意',‘而不是",“分隔符和strtok_f而不是strtok函数):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int main (int argc, char *argv[])
{
    char str[] = "$GPRMC,105954.000,A,3150.6731,N,11711.9399,E,0.00,96.10,250313,,,A*53";
    char* Message_ID = strtok_f(str,',');
    char* Time = strtok_f(NULL,',');
    char* Data_Valid = strtok_f(NULL,',');
    char* Raw_Latitude = strtok_f(NULL,',');
    char* N_S = strtok_f(NULL,',');
    char* Raw_Longitude = strtok_f(NULL,',');
    char* E_W = strtok_f(NULL,',');
    char* Speed = strtok_f(NULL,',');
    char* COG = strtok_f(NULL,',');
    char* Date = strtok_f(NULL,',');
    char* Magnetic_Variation = strtok_f(NULL,',');
    char* M_E_W = strtok_f(NULL,',');
    char* Positioning_Mode = strtok_f(NULL,',');

    double Latitude = atof(Raw_Latitude);
    double Longitude = atof(Raw_Longitude);

    printf("The Message ID is : %s\n", Message_ID);
    printf("The Time is : %s\n", Time);
    printf("The data valid is : %s\n", Data_Valid);
    printf("The Latitude is : %f\n", Latitude);
    printf("The N_S is : %s\n", N_S);
    printf("The Longitude is : %f\n", Longitude);
    printf("The E_W is : %s\n", E_W);
    printf("The Speed is : %s\n", Speed);
    printf("The COG is : %s\n", COG);
    printf("The Date is : %s\n", Date);
    printf("The Magnetic_Variation is : %s\n", Magnetic_Variation);
    printf("The M_E_W is : %s\n", M_E_W);
    printf("The Positioning_Mode is : %s\n", Positioning_Mode);

    return 0;
}

现在的结果:

消息ID是:$GPRMC 时间是: 105954.000 有效的数据是: 纬度是: 3150.673100 N_S是:n 经度是: 11711.939900 E_W是:e 速度是: 0.00 组委会为: 96.10 日期是: 250313 Magnetic_Variation是: M_E_W是: Positioning_Mode是: A*53 C:\Users\froca\Desktop\strtok>

请注意,“磁性变化”和"M_E_W“现在是空标记。那才是关键。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48486952

复制
相关文章
Linux项目实战系列之:GPS数据解析
在之前一篇文章:嵌入式Linux系列第21篇:应用程序之开篇闲聊 里,当时给自己定了一个小目标,要实现如下功能的小项目:
用户2366192
2021/05/31
1.5K0
C语言中的字符串处理
•字符串字面量(字符串常量,在C标准中称为,字符串字面量)如何存储字符串字面量  从本质上而言,C/C++
Java架构师必看
2021/03/22
1.2K0
C语言中.h和.c文件解析
简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程:
用户6754675
2020/07/14
3K0
从Ndom语浅谈语言中的进制
这题粗看复杂,其实不然。首先不难看出,abo、an并不是数字,所以不是加法就是乘法。因为abo出现的十分多,所以我们可以简单地假设abo是加法。接下来需要确定进制。我们知道1-10的乘方之间,出现了三个单独的词。不难得出,肯定1个是1,一个是基数的平方。除了这两个,只剩一个单独的词,那么这个词只可能是2^2=4。由此我们可以确定,Ndom语言的数字表达的基数肯定大于4且小于9。因为nif为很多长词的开头,所以nif应该是基数的平方。在题2的等式我们发现meregh乘上sas结尾的词,结果竟然还是以meregh尾!所以很明显sas就是1,于是thonith就是4。接着找,就找到了余下几个小于基数的词(于abo、an之后的较小):ithin、meregh、thef(可能是2、3、5)。剩下的mer、nif、tondor估计就是基数的倍数了,通过观察nif abo tondor abo mer abo thonith,发现nif>tondor>mer。按照推论,mer abo ithin应该是第三小的数字——9,那么mer应该就是基数了。ithin肯定不是1、4,所以排除5、8进制可能。那么就只剩下6、7进制两种可能了。分析得mer an thef abo thonith是第4小的,即16。mer*thef+4=16⇒mer*thef=12。所以只有一种可能:Ndom语言的数字是6进制。所以mer为6,thef为2,nif是mer的平方即36,ithin是9-6=3。排除法得,meregh是5。最后还有一个tondor,通过推断tondor abo mer abo sas≥6*2+6+1=19最近的平方数是25,可以判断tondor是18。至此,我们已经推断完成所有的词。剩下就是一些小小的规则,比如表示72,并不是nif an thef,而是直接nif thef。还有就是大的数字一定会在前。所以我们就能写出:58=36+18+4也就是nif abo tondor abo thonith,而87=36*2+6*2+3即nif thef abo mer an thef abo ithin。参考答案:
KAAAsS
2022/01/13
11.1K0
从Ndom语浅谈语言中的进制
C语言中的字符串操作分析
C语言中关于字符串的函数很多,并单独建立一个基于字符串操作的头文件,string.h。
鲁郭大侠
2020/03/12
1.1K0
C语言中的字符串可以怎么处理?
char strncpy(char s1,const char *s2,size_t n);
小林C语言
2020/09/17
1.4K0
C语言中定义字符串的几种方式
  由于字符串本质上其实就是以'\0作为'结尾的特殊字符数组,所以定义字符串时,必须保证字符串存储的最后一个元素为'\0'。
诸葛青云
2020/03/11
9.4K0
C语言中定义字符串的几种方式
[日常] C语言中的字符数组和字符串
c语言字符数组和字符串: 1.存放字符的数组称为字符数组 char str[] 2.'\0'也被称为字符串结束标志 3.由" "包围的字符串会自动在末尾添加'\0' 4.逐个字符地给数组赋值并不会自动添加'\0' 5.局部变量初始化为零值会自动添加结束标志 6.直接使用一个指针指向字符串的形式 char* str 7.最根本的区别是在内存中的存储区域不一样,字符数组存储在全局数据区或栈区,第二种形式的字符串存储在常量区。全局数据区和栈区的字符串(也包括其他数据)有读取和写入的权限,而常量区的字符串(也包括其他数据)只有读取权限,没有写入权限。
唯一Chat
2019/09/10
2.4K0
C语言中的字符串可以怎么处理?
char strncpy(char s1,const char *s2,size_t n);
小林C语言
2020/12/24
1.2K0
C语言中的字符串可以怎么处理?
C语言中.h和.c文件解析(很精彩)
简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程:
用户7515259
2020/09/02
1.7K0
c语言中(int)什么意思_c语言中怎么用int转化char
int是C++关键字,表示整型,其大小是32位有符号整型,表示的范围是-2,147,483,648 到2,147,483,647;
全栈程序员站长
2022/09/23
4.9K0
c语言中(int)什么意思_c语言中怎么用int转化char
c语言中求字符串的长度的函数_c语言求最大字符串
在C语言中求字符串的长度,可以使用sizeof()函数和strlen()函数,后者需要引入string.h (#include <string.h>)
全栈程序员站长
2022/09/20
3K0
c语言中toupper函数_c中输出字符串的函数
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/168040.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/20
1.1K0
c字符串详细解析
都是字符串字面常量,其中const char*表示这个指针指向的内存是只读的,不能修改里面的内容。
秋名山码神
2022/12/13
3720
c字符串详细解析
c语言中字符串比较的库函数是什么_c语言比较字符串大小
在 单片机串口实现字符串命令解析 这篇文章中分析了在串口通信中如何去解析字符串命令,这篇文章就来讨论下字符串比较的方法都有哪些?
全栈程序员站长
2022/11/17
2K0
c语言中字符串比较的库函数是什么_c语言比较字符串大小
【说站】c语言中fread函数怎么用
2、fread函数不区分文件的尾部和错误,因此调用者必须使用feof和ferror来判断发生了什么。
很酷的站长
2022/11/24
1.6K0
【说站】c语言中fread函数怎么用
MySQL字符串分割_c语言中如何截取字符串
一、字符串拆分: SUBSTRING_INDEX(str, delim, count)
全栈程序员站长
2022/11/08
2.9K0
MySQL字符串分割_c语言中如何截取字符串
c语言中的offset_c语言中/和%的区别
今天看libPhenom源代码,看到他们使用的JSON解析库参考的是Jansson JSON解析库。于是就去网上查了这个库,找到了官方网站:http://www.digip.org/jansson/。找了一下发现在Github上能够下载源代码,于是下载了源代码来瞅瞅。
全栈程序员站长
2022/09/23
2.5K0
【C字符串函数】——对C语言中有关字符串库函数的实现及模拟
我们已经了解了C语言中很多数据类型,比如int(整数类型)、char(字符类型)、以及浮点型的double(双精度)、float(单精度),但是有一点就是我们发现这里并没有提到我们常见的有关字符串的类型。其实在C语言中,字符串通常是放在 常量字符串 中或者 字符数组 中的。(常量字符串是不可被修改的)
诺诺的包包
2023/02/17
1.1K0
【C字符串函数】——对C语言中有关字符串库函数的实现及模拟
C语言中如何实现数据帧封装与解析
在计算机网络通信中,数据帧的封装与解析是非常重要的环节。本文将介绍一种基于C语言的实现方法,旨在帮助读者理解数据帧的结构和实现过程。
用户10354340
2023/08/13
6410

相似问题

microchip环境下c++/c语言中nmea csv的解析

10

解析GNSS - NMEA字符串

10

用C++验证NMEA语句

11

C#开源NMEA解析器

42

GPS NMEA字符串的解析代码

70
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文