C 中的字符串解析、存储和读取

发布于 2024-12-11 10:53:13 字数 5182 浏览 0 评论 0原文

我编写了一个函数来解析 NMEA 句子,将参数存储在单独的数组中并写入它们的值。

首先,我在控制台中运行它,一切都按预期工作。 main() 中测试命令的函数如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    //$GPSACP: 200949.000,4603.9172N,01429.5821E,1.0,337.8,3,53.82,0.36,0.19,231011,06


    char *get_substring(size_t start, size_t stop, const char *src, char *dst, size_t size)
    {
        int count = stop - start;
       if ( count >= --size )
       {
          count = size;
       }
       sprintf(dst, "%.*s", count, src + start);
       return dst;
    }

    void get_separator_position(char *input_string, int *separators_array, int separators_count)
    {
        //10 separators
        char *separator = ",";
        char *current_string = input_string;
        int current = 0;
        char *found;
        int pos;
        int cur_pos = 0;
        for(current = 0; current < separators_count; current++)
        {
                found = strstr(current_string, separator);
                if(found != NULL)
                {
                     pos = found - current_string;
                     cur_pos += pos;
                     separators_array[current] = cur_pos + current;
                     current_string = &input_string[cur_pos + 1 + current];


                }
                else
                {
                    //printf("Not found!\n");
                }
        }
    }

    void parse_nmea_string(char *nmea_string, char *utc, char *latitude, char *longitude, char *hdop, char *altitude, char *fix, char *cog, char *spkm, char *spkn, char *date, char *nsat)
    {
         //10 separators "," in NMEA sentence
         int separators_array[10];
         get_separator_position(nmea_string, &separators_array[0], 10);
         int length = strlen(nmea_string);
         utc = get_substring(9, separators_array[0] + 1, nmea_string, utc, sizeof(char) * (separators_array[0] - 9 + 1));
         latitude = get_substring(separators_array[0] + 1, separators_array[1], nmea_string, latitude, sizeof(char) * (separators_array[1] - separators_array[0]));
         longitude = get_substring(separators_array[1] + 1, separators_array[2], nmea_string, longitude, sizeof(char) * (separators_array[2] - separators_array[1]));
         hdop = get_substring(separators_array[2] + 1, separators_array[3], nmea_string, hdop, sizeof(char) * (separators_array[3] - separators_array[2]));
         altitude = get_substring(separators_array[3] + 1, separators_array[4], nmea_string, altitude, sizeof(char) * (separators_array[4] - separators_array[3]));
         fix = get_substring(separators_array[4] + 1, separators_array[5], nmea_string, fix, sizeof(char) * (separators_array[5] - separators_array[4]));
         cog = get_substring(separators_array[5] + 1, separators_array[6], nmea_string, cog, sizeof(char) * (separators_array[6] - separators_array[5]));
         spkm = get_substring(separators_array[6] + 1, separators_array[7], nmea_string, spkm, sizeof(char) * (separators_array[7] - separators_array[6]));
         spkn = get_substring(separators_array[7] + 1, separators_array[8], nmea_string, spkn, sizeof(char) * (separators_array[8] - separators_array[7]));
         date = get_substring(separators_array[8] + 1, separators_array[9], nmea_string, date, sizeof(char) * (separators_array[9] - separators_array[8]));
         nsat = get_substring(separators_array[9] + 1, length, nmea_string, nsat, sizeof(char) * (length - separators_array[9]));
    }

    int main(int argc, char *argv[])
    {


static const char text[] = "$GPSACP: 200949.000,4603.9172N,01429.5821E,1.0,337.8,3,53.82,0.36,0.19,231011,06";
    char utc[20];
      char latitude[30];
      char longitude[20];
      char hdop[20];
      char altitude[20];
      char fix[20];
      char cog[20];
      char spkm[20];
      char spkn[20];
      char date[20];
      char nsat[20];
      printf("Separator %d at position %d\n", pos, separators_array[pos]);
      parse_nmea_string(text, utc, latitude, longitude, hdop, altitude, fix, cog, spkm, spkn, date, nsat);
      printf("UTC: %s\n", utc);
      system("PAUSE");  
      return 0;
    }

该代码工作正常,测试输出为

UTC: 200949.000

然后我尝试在微控制器项目上使用上述函数,并使用现有的 debug_str() 函数写入数组值以下:

// Debug function prints string msg to UART1 (to PC) 
void debug_str(const char* msg)
{
#ifdef debug
    putchar1(0x24);   //$
    while(*msg) 
    {
       putchar1(*msg++);    
    }
    putchar1(0x0D); //Carriage Return
#endif
}

因此,将解析函数与现有代码结合起来,我尝试按以下方式编写数组值:

char UTC[15];
char latitude[15]; 
char longitude[15];
char hdop[6];
char altitude[9];
char fix[5];
char cog[10];
char spkm[8];
char spkn[8];
char date[10];
char nsat[6];

static const char nmea_test[] = "$GPSACP: 200949.000,4603.9172N,01429.5821E,1.0,337.8,3,53.82,0.36,0.19,231011,06";
    ...

    parse_nmea_string(nmea_test, UTC, latitude, longitude, hdop, altitude, fix, cog, spkm, spkn, date, nsat); 
    debug_str(latitude);

但这种方式输出不正确。

输出:

$*s

有人知道问题是什么以及如何正确存储从字符串 nmea_test 解析的参数并将其写入输出吗?

谢谢你!

I wrote a functions to parse a NMEA sentence, store parameters in separate arrays and write their values.

First I ran it in console and everything worked as expected. The functions along the test commands in main() are the following:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    //$GPSACP: 200949.000,4603.9172N,01429.5821E,1.0,337.8,3,53.82,0.36,0.19,231011,06


    char *get_substring(size_t start, size_t stop, const char *src, char *dst, size_t size)
    {
        int count = stop - start;
       if ( count >= --size )
       {
          count = size;
       }
       sprintf(dst, "%.*s", count, src + start);
       return dst;
    }

    void get_separator_position(char *input_string, int *separators_array, int separators_count)
    {
        //10 separators
        char *separator = ",";
        char *current_string = input_string;
        int current = 0;
        char *found;
        int pos;
        int cur_pos = 0;
        for(current = 0; current < separators_count; current++)
        {
                found = strstr(current_string, separator);
                if(found != NULL)
                {
                     pos = found - current_string;
                     cur_pos += pos;
                     separators_array[current] = cur_pos + current;
                     current_string = &input_string[cur_pos + 1 + current];


                }
                else
                {
                    //printf("Not found!\n");
                }
        }
    }

    void parse_nmea_string(char *nmea_string, char *utc, char *latitude, char *longitude, char *hdop, char *altitude, char *fix, char *cog, char *spkm, char *spkn, char *date, char *nsat)
    {
         //10 separators "," in NMEA sentence
         int separators_array[10];
         get_separator_position(nmea_string, &separators_array[0], 10);
         int length = strlen(nmea_string);
         utc = get_substring(9, separators_array[0] + 1, nmea_string, utc, sizeof(char) * (separators_array[0] - 9 + 1));
         latitude = get_substring(separators_array[0] + 1, separators_array[1], nmea_string, latitude, sizeof(char) * (separators_array[1] - separators_array[0]));
         longitude = get_substring(separators_array[1] + 1, separators_array[2], nmea_string, longitude, sizeof(char) * (separators_array[2] - separators_array[1]));
         hdop = get_substring(separators_array[2] + 1, separators_array[3], nmea_string, hdop, sizeof(char) * (separators_array[3] - separators_array[2]));
         altitude = get_substring(separators_array[3] + 1, separators_array[4], nmea_string, altitude, sizeof(char) * (separators_array[4] - separators_array[3]));
         fix = get_substring(separators_array[4] + 1, separators_array[5], nmea_string, fix, sizeof(char) * (separators_array[5] - separators_array[4]));
         cog = get_substring(separators_array[5] + 1, separators_array[6], nmea_string, cog, sizeof(char) * (separators_array[6] - separators_array[5]));
         spkm = get_substring(separators_array[6] + 1, separators_array[7], nmea_string, spkm, sizeof(char) * (separators_array[7] - separators_array[6]));
         spkn = get_substring(separators_array[7] + 1, separators_array[8], nmea_string, spkn, sizeof(char) * (separators_array[8] - separators_array[7]));
         date = get_substring(separators_array[8] + 1, separators_array[9], nmea_string, date, sizeof(char) * (separators_array[9] - separators_array[8]));
         nsat = get_substring(separators_array[9] + 1, length, nmea_string, nsat, sizeof(char) * (length - separators_array[9]));
    }

    int main(int argc, char *argv[])
    {


static const char text[] = "$GPSACP: 200949.000,4603.9172N,01429.5821E,1.0,337.8,3,53.82,0.36,0.19,231011,06";
    char utc[20];
      char latitude[30];
      char longitude[20];
      char hdop[20];
      char altitude[20];
      char fix[20];
      char cog[20];
      char spkm[20];
      char spkn[20];
      char date[20];
      char nsat[20];
      printf("Separator %d at position %d\n", pos, separators_array[pos]);
      parse_nmea_string(text, utc, latitude, longitude, hdop, altitude, fix, cog, spkm, spkn, date, nsat);
      printf("UTC: %s\n", utc);
      system("PAUSE");  
      return 0;
    }

This code works fine and the test output is

UTC: 200949.000

Then I tried to use the above function on the microcontroller project and write the array values using the existing debug_str() function which is the following:

// Debug function prints string msg to UART1 (to PC) 
void debug_str(const char* msg)
{
#ifdef debug
    putchar1(0x24);   //$
    while(*msg) 
    {
       putchar1(*msg++);    
    }
    putchar1(0x0D); //Carriage Return
#endif
}

So combining the parsing functions with existing code I tried to write the array values the following way:

char UTC[15];
char latitude[15]; 
char longitude[15];
char hdop[6];
char altitude[9];
char fix[5];
char cog[10];
char spkm[8];
char spkn[8];
char date[10];
char nsat[6];

static const char nmea_test[] = "$GPSACP: 200949.000,4603.9172N,01429.5821E,1.0,337.8,3,53.82,0.36,0.19,231011,06";
    ...

    parse_nmea_string(nmea_test, UTC, latitude, longitude, hdop, altitude, fix, cog, spkm, spkn, date, nsat); 
    debug_str(latitude);

But this way the output was not correct.

Output:

$*s

Does anyone what the problem is and how to correctly store and write to the output the parameters which are parsed from the string nmea_test?

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泡沫很甜 2024-12-18 10:53:13

你应该了解 C 中数组和指针之间的区别。
阅读任何关于这方面的优秀 C 教科书。

您的 get_substring 函数未达到您的预期。它不会为其结果分配任何字符串。

您可以考虑在 get_substring 中使用 strdup,并采用调用者应释放结果的约定。

You should understand the difference between arrays and pointers in C.
Read any good C textbook about this.

Your get_substring function don't do what you expect. It does not allocate any string for its result.

You might consider using strdup inside get_substring, and adopt the convention that the caller should free the result.

年少掌心 2024-12-18 10:53:13

现在可以了。函数 get_substring 和 get_separator_positions 必须按以下方式修改:

char *get_substring(unsigned int start, unsigned int stop, const char *src, char *dst, unsigned int size)
{
    int count = stop - start;
    if ( count >= --size )
    {
      count = size;
    }
  // sprintf(dst, "%.*s", count, src + start); - this line was replaced by the following two lines (the microcontroller does not support strdup so strncpy had to be used)

    strncpy(dst, &src[start], size);
    dst[size] = '\n';
   return dst;
}


//char input_string[] = "$GPSACP: 200949.000,4603.9172N,01429.5821E,1.0,337.8,3,53.82,0.36,0.19,231011,06";

void get_separator_position(char *input_string, int *separators_array, int separators_count)
{
    //10 separators
    char separator[] = ",";//char *separator = "," didn't work
    char *current_string = input_string;
    int current = 0;
    char *found;
    int pos;
    int cur_pos = 0;

    //char tmp_pos[10];

    for(current = 0; current < separators_count; current++)
    {
            found = strstr(current_string, separator);
            if(found != NULL)
            {
                 debug_str("found!");
                 //debug_str(found);
                 pos = found - current_string;

//                 itoa(pos,tmp_pos);
//                 debug_str(tmp_pos);
                 cur_pos += pos;

                 separators_array[current] = cur_pos + current;
                 current_string = &input_string[cur_pos + 1 + current];
            }
            else
            {
                debug_str("Not found!");
            }
    }
}

Now it works. Functions get_substring and get_separator_positions had to be modified the following way:

char *get_substring(unsigned int start, unsigned int stop, const char *src, char *dst, unsigned int size)
{
    int count = stop - start;
    if ( count >= --size )
    {
      count = size;
    }
  // sprintf(dst, "%.*s", count, src + start); - this line was replaced by the following two lines (the microcontroller does not support strdup so strncpy had to be used)

    strncpy(dst, &src[start], size);
    dst[size] = '\n';
   return dst;
}


//char input_string[] = "$GPSACP: 200949.000,4603.9172N,01429.5821E,1.0,337.8,3,53.82,0.36,0.19,231011,06";

void get_separator_position(char *input_string, int *separators_array, int separators_count)
{
    //10 separators
    char separator[] = ",";//char *separator = "," didn't work
    char *current_string = input_string;
    int current = 0;
    char *found;
    int pos;
    int cur_pos = 0;

    //char tmp_pos[10];

    for(current = 0; current < separators_count; current++)
    {
            found = strstr(current_string, separator);
            if(found != NULL)
            {
                 debug_str("found!");
                 //debug_str(found);
                 pos = found - current_string;

//                 itoa(pos,tmp_pos);
//                 debug_str(tmp_pos);
                 cur_pos += pos;

                 separators_array[current] = cur_pos + current;
                 current_string = &input_string[cur_pos + 1 + current];
            }
            else
            {
                debug_str("Not found!");
            }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文