簡體   English   中英

在 C 中使用 strok 解析 NMEA 字符串

[英]Parsing a NMEA String using strok in C

我正在嘗試使用帶有分隔符"," 的strtok 函數解析 GNRMC 字符串,當我注意到一些我沒有預料到的不同時,一切都很順利。 如果字符串包含連續的“,”,則 strtok 超調和打印功能錯位真實數據,我的目標是在連續的“,”之間沒有可用數據時打印數字0

我該怎么做。?

這是我的代碼

#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;
}

輸出窗口輸出窗口

如果您只檢測到一個特定字符(如',' ),那么直接的方法是使用舊的strchr()

 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;
 ...

一個棘手的宏可以簡化使用:

#define FIND_AND_NUL(s, p, c) ( \
   (p) = strchr(s, c), \
   *(p) = '\0', \
   ++(p), \
   (p))

像這樣使用它:

 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, ',');
 ...

我使用自己的 strtok 函數,該函數非常簡單,但與原始函數有兩個不同之處:(1) 分隔符只是單個字符而不是字符串 (2) 如果要解析的字符串有兩個連續的分隔符,則該函數返回一個空的非 -空標記“”。 這對於解析 NMEA 消息非常方便。

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;
}

非遞歸版本:

char *strtok_f (char *s, char delim)
{
    static char *save_ptr;

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

所以,你的例子(注意','而不是“,”分隔符和strtok_f而不是strtok函數):

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
有效數據為:A
緯度是: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:\\用戶\\froca\\桌面\\strtok>

請注意,“Magnetic Variation”和“M_E_W”現在是空標記。 這就是關鍵。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM