我正在尝试使用|
解析带有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
显示的行为是通常的行为,我只是想要另一种方法来获得所需的结果,而不是解释为什么会发生这种情况。
答案 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;
}