我有一个包含
等数据的CSV文件value;name;test;etc
我尝试使用strtok(string, ";")
进行拆分。但是,此文件可以包含零长度数据,如下所示:
value;;test;etc
strtok()
跳过。有没有办法可以避免strtok
像这样跳过零长度数据?
答案 0 :(得分:5)
可能的替代方法是使用BSD函数strsep()
而不是strtok()
(如果可用)。
来自man page:
strsep()
函数旨在替代strtok()
功能。虽然strtok()
函数应该是首选 便携性原因(符合ISO / IEC 9899:1990(“ISO C90”)) 它无法处理空字段,即检测由其分隔的字段 两个相邻的分隔符,或者用于多个分隔符 一次一个字符串。strsep()
函数首次出现在 4.4BSD。
一个简单的例子(也从该手册页复制):
char *token, *string, *tofree;
tofree = string = strdup("value;;test;etc");
while ((token = strsep(&string, ";")) != NULL)
printf("token=%s\n", token);
free(tofree);
输出:
token=value token= token=test token=etc
所以空字段处理正确。
当然,正如其他人已经说过的那样,这些简单的标记化函数都没有处理 引号内的分隔符正确,所以如果这是一个问题,你应该使用 一个正确的 CSV解析库。
答案 1 :(得分:4)
没有办法让strtok()
不这样做。来自man page:
解析后的两个或多个连续分隔符字节的序列 string被认为是一个单独的分隔符。分隔符字节在 字符串的开头或结尾被忽略。换句话说:代币 由strtok()返回的字符串总是非空字符串。
但您可以执行的操作是检查令牌之前'\0'
个字符的数量,因为strtok()
会将所有遇到的令牌替换为'\0'
。这样你就会知道有多少令牌被跳过了。 Source info:
令牌的这一端自动被空字符替换, 并且函数返回令牌的开头。
代码示例以显示我的意思。
char* aStr = ...;
char* ptr = NULL;
ptr = strtok (...);
char* back = ptr;
int count = -1;
do {
back--;
if (back <= aStr) break; // to protect against reads before aStr
count++;
} while (*back = '\0');
(没有ide或测试的书面,可能是一个无效的实现,但这个想法代表)。
答案 2 :(得分:2)
不,你不能。 来自“man strtok”:
一个包含两个或多个连续分隔符的序列 解析的字符串被认为是单个分隔符。分隔符 字符串开头或结尾的字符将被忽略。放 另一种方式:strtok()返回的标记总是非空的 字符串。
如果您的数据包含引号内的分隔符或任何其他“转义”,您也可能会遇到问题。
我认为最好的解决方案是获取CSV解析库或编写自己的解析函数。