解析缺少条目的csv文件

时间:2013-11-30 15:32:41

标签: c parsing csv

我正在尝试使用|解析带有C的csv文件,其中分隔符为strtok。问题是某些字段是空的,因此两个分隔符彼此相邻放置。好像strtok只是跳过所有空字段而只是输出下一个非空字段。

问题是我需要知道正在读取的令牌属于哪个位置。

这是一个非常小的例子来说明。

FILE

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

例如,这一行有10个字段,但只有字段1,2,9和10有一些值。

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

输出

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

预期输出

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

有没有其他方法像预期一样解析这样的行?之前未定义行中元素的数量。

我已经知道strtok显示的行为是通常的行为,我只是想要另一种方法来获得所需的结果,而不是解释为什么会发生这种情况。

2 个答案:

答案 0 :(得分:3)

我不确定你在哪个平台上,但是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++;
   }
}

答案 1 :(得分:2)

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