// Previous code is needed to point strtok to a string and start ingesting from it.
char * field_string = strtok(NULL, ',');
// Note that this can't be done after the first call to strtok for a given buffer, since the previous character would be outside of the string's memory space.
if (*(field_string-1) == '\0') {
// no delimiters were skipped
} else {
// one or more delimiters were skipped
}
char *ptr = strtok(line, ",");
char *arr[20]; // Your max may vary. Checking for overflows is an exercise for the reader
int i = 0;
while (ptr != NULL)
{
char *back = ptr-2; // go back 2 to check for extra tokens
// Not all deliminators are converted to nulls, so check for commas too
while ((*back == '\0' || *back == ',') && (back > line))
{
arr[i++] = back; // Some of these may be pointers to comma strings
back--;
}
arr[i++] = ptr;
ptr = strtok(NULL, ",");
}
5条答案
按热度按时间cfh9epnr1#
一种可能的替代方法是使用BSD函数
strsep()
代替strtok()
(如果可用)。strsep()
函数是strtok()
函数的替代函数。由于可移植性的原因,strtok()
函数应该是首选的(它符合ISO/IEC 9899:1990(“ISO C90”)),它不能处理空字段,即检测由两个相邻的定界符分隔的字段,或一次用于多个字符串。strsep()
函数最早出现在4.4BSD中。下面是一个简单的示例(也是从该手册页复制的):
输出:
因此空字段被正确地处理。
当然,正如其他人已经说过的,这些简单的标记器函数都不能正确处理引号内的分隔符,因此如果这是一个问题,您应该使用一个 proper CSV解析库。
r6hnlfcb2#
无法使
strtok()
不以这种方式运行。从man page:解析字符串中两个或多个连续分隔符字节的序列被视为单个分隔符。字符串开头或结尾的分隔符字节将被忽略。换句话说:strtok()返回的标记总是非空字符串。
但是你可以做的是检查标记之前的
'\0'
字符数,因为strtok()
会将所有遇到的标记替换为'\0'
,这样你就知道跳过了多少个标记。Source info:标记的结尾自动替换为空字符,标记的开头由函数返回。
和一个代码示例来说明我的意思。
(在没有IDE或测试的情况下编写,可能是无效的实现,但想法成立)。
nsc4cvqm3#
不,你不能。来自"man strtok":
解析字符串中两个或多个连续分隔符的序列被视为单个分隔符。字符串开头或结尾的分隔符将被忽略。换句话说:strtok()返回的标记总是非空字符串。
如果数据在引号或任何其他"转义"中包含分隔符,也可能会遇到问题。
我认为最好的解决方案是获得CSV解析库或编写自己的解析函数。
ma8fv8wu4#
从最近的经验来看,strtok()并不一定要用字符串结尾字符替换所有的分隔符,而是用字符串结尾字符替换它找到的第一个分隔符,并跳过后面的分隔符,但将它们保留在原处。
这意味着在名义上的情况下(分隔符之前没有零长度字符串),在第一次调用strtok()之后,每次调用strtok()都将返回一个指针,指向从
\0
字符开始的字符串。如果strtok()读取分隔符之间长度为零的字符串,strtok()将返回一个指针,该指针指向在尚未替换为
\0
的分隔符字符之后开始的字符串。下面是我的解决方案,用于确定strtok()是否跳过了分隔符之间的零长度字符串。
sauutmhj5#
如果strsep()不可用,这是我的解决方案,它建立在@Dariusz的方法上,在我的例子中,我想创建一个指针数组,这些指针指向索引与原始字符串中的字段位置匹配的标记。
另外,我使用逗号而不是分号作为分隔符,代码如下所示: