Parsing csv file with missing entries

c, csv, parsing

Solution

I am not sure what platform you are on, but strsep() is the recommended replacement for what you are trying to do.

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

Problem

I am trying to parse a csv file with C where the separator is `|` using `strtok`. The problem is that some fields are empty and thus two separators are placed next to each other. It seems that `strtok` is just skipping all empty fields and just outputting the next non-empty field. The thing is that I need to know at which position the token that is being read belongs to. Here is a very small example to illustrate. FILE ``` node|171933|||traffic_signals|||||40.4200658|-3.7016652 ``` This line for instance has 10 fields, but only field 1,2,9 and 10 have 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"); } } ``` OUTPUT ``` Element 0: node Element 1: 171933 Element 2: traffic_signals Element 3: 40.4200658 Element 4: -3.7016652 ``` EXPECTED OUTPUT ``` 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 line like this as expected? The number of elements in a line is not defined previously. I already know that the behaviour shown by `strtok` is the usual behaviour I am just asking for another way of doing it to obtain the desired results, not for the explanation of why this happens.

Original source