Parsing a csv file with missing entries

I am trying to parse a csv file with C, where the delimiter is |using strtok. The problem is that some fields are empty, and therefore the two delimiters are located next to each other. It seems to strtokjust skip all the empty fields and just display the next non-empty field.

The fact is that I need to know in which position the token that is being read belongs.

Here is a small example to illustrate.

FILE

node|171933|||traffic_signals|||||40.4200658|-3.7016652

This line, for example, has 10 fields, but only the field 1,2,9 and 10 has some value in it.

CODE

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

void main()
{
    FILE *fp;
    char lineBuf[128];
    char *token;
    int i=0;

    if((fp = fopen("test.txt", "r"))==NULL){
      fprintf (stderr, "\nError when opening file\n");
      return ;
    }

    fgets (lineBuf, sizeof(lineBuf), fp);

    token=strtok(lineBuf, "|\n");
    while(token!=NULL){
      printf("Element %d: %s\n",i,token); i++;
      token=strtok(NULL, "|\n");
    }
}

EXIT

Element 0: node
Element 1: 171933
Element 2: traffic_signals
Element 3: 40.4200658
Element 4: -3.7016652

EXPECTED EXIT

Element 0: node
Element 1: 171933
Element 4: traffic_signals
Element 9: 40.4200658
Element 10: -3.7016652

Is there any other way to parse a string like this, as expected? The number of elements in a row is not defined previously.

, , strtok, , , .

+4
2

, , strsep() - , .

man strsep

while (fgets(buf, BUFSIZE, fp) != NULL) {
    char *line  = buf;
    char *field;
    int index = 0;
    while ((field = strsep(&line, "|")) != NULL) {
        /* note the trailing field will contain newline. */
        printf("element %d = %s\n", index, field);
        index++;
   }
}
+3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//non skip version strtok
char *my_strtok_r(char *str, const char *delims, char **store){
    char *p, *wk;
    if(str != NULL){
        *store = str;
    }
    if(*store == NULL) return NULL;
    //*store += strspn(*store, delims);//skip delimiter
    if(**store == '\0') return NULL;
    p=strpbrk(wk=*store, delims);
    if(p != NULL){
        *p='\0';
        *store = p + 1;
    } else {
        *store = NULL;
    }
    return wk;
}

char *my_strtok(char *str, const char *delims){
    static char *p;
    return my_strtok_r(str, delims, &p);
}

int main(void){
    char lineBuf[128] = "node|171933|||traffic_signals|||||40.4200658|-3.7016652\n";
    char *token;
    int i=0;

    token=my_strtok(lineBuf, "|\n");
    while(token!=NULL){
        if(*token)//token != "";
            printf("Element %d: %s\n",i,token); 
        i++;
        token=my_strtok(NULL, "|\n");
    }
    return 0;    
}
+2

All Articles