Home > other >  Parse comma separated string in C
Parse comma separated string in C

Time:09-17

Currently I'm trying this, which is printing out nothing (but there are no compilation problems):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void parseGprmc(char* gprmc) {
    printf("test");
    char* ptr;
    ptr = strtok(gprmc, ",");

    while(ptr != NULL) {
        printf("%s\n", ptr);
        ptr = strtok(gprmc, ",");
    }
}

int main() {
    char* gprmc = "$GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,,,E*62";

    printf("%s", gprmc);
    parseGprmc(gprmc);
    printf("%s", gprmc);

    return 1;
}

What am I doing wrong?

Ideally, parseGprmc would print out:

$GPRMC
081836
A
3751.65
S
14507.36
E
000.0
360.0


E*62

Considering the null values as valid as well but I don't think that strtok does that.

CodePudding user response:

There are two serious issues in your code. First (as pointed out in the comments), the strtok function modifies the string given as its first argument – but you have declared gprmc as a pointer to a constant (immutable) string literal. To fix this, change the declaration to a char array that is initialized with a copy of the literal:

    char gprmc[] = "$GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,,,E*62";

Second, only the first call to strtok for parsing a given string should have that string as its first argument; subsequent calls (on the same string) should use a NULL first argument (see this cppreference, particularly the part beginning with If str is not a null pointer, ….

Here is a 'fixed' version of your parseGprmc function:

void parseGprmc(char* gprmc)
{
    printf("test");
    char* ptr;
    ptr = strtok(gprmc, ","); // First call, use string address
    while (ptr != NULL) {
        printf("%s\n", ptr);
        ptr = strtok(NULL, ","); // Subsequent calls, use NULL
    }
}

Note that it is not directly possible to extract empty (null) tokens using the strtok function, as the function searches for the first character which is not contained in delim (quoted from the same cppreference page). To do this, you have to add some 'tricks', comparing the returned address of each token with the address of the end of the previous token, and counting how many delimiter characters were in the 'gap'. Here is a possible modification of your function to do just that:

void parseGprmc(char* gprmc)
{
    printf("test");
    char* ptr;
    char* lastend;
    ptrdiff_t nBlanks;
    ptr = strtok(gprmc, ","); // First call, use string address
    while (ptr != NULL) {
        lastend = ptr   strlen(ptr); // Address of last character in token
        printf("%s\n", ptr);
        ptr = strtok(NULL, ","); // Subsequent calls, use NULL
        nBlanks = ptr ? ptr - lastend : -1; // Number of delimiters found
        while (--nBlanks >= 1) { // One empty token for each gap > 1
            printf("<null token>\n");
        }
    }
}

CodePudding user response:

One remark about strtok is that you must use NULL for the second and next calls. This is because after the first call the contents of gprmc is modified and has an \0 in place of first ,

ptr = strtok(gprmc, ","); // for first call before the loop

ptr = strtok(NULL, ",");// for the call following in the loop

CodePudding user response:

homework? inside the loop you don't pass strtok a pointer, you pass NULL. See help on that function. But perhaps what you're wanting is to use strchr instead and change ',' to '\n' ?

CodePudding user response:

strcspn can be used to parse a literal string.
The specifer %s precision field %.*s is used to print only span characters from the string.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void parseGprmc(char* gprmc) {
    int span = 0;

    printf("test\n");
    while( *gprmc) {
        span = strcspn ( gprmc, ",");
        if ( span) {
            printf("%.*s\n", span, gprmc);
        }
        else {
            printf("empty field\n");
        }
        gprmc  = span   1;
    }
}

int main() {
    char* gprmc = "$GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,,,E*62";

    printf("%s\n", gprmc);
    parseGprmc(gprmc);
    printf("%s\n", gprmc);

    return 1;
}
  • Related