我有一个文件,其中某些字段由制表符分隔。总会有17个标签,但订单可能会有所不同,例如..
75104\tDallas\t85\t34.46\t45.64
75205\tHouston\t\t37.34\t87.32
93434\t\t\t1.23\t3.32
当我以下列方式使用strtok
时
while (fgets(buf, sizeof(buf), fp) != NULL) {
tok = strtok(buf,"\t");
while(tok != NULL) {
printf("%s->",tok);
tok = strtok(NULL,"\t");
}
}
我获得了所有令牌,但忽略了双标签\t\t
或更多。但是,我需要知道字段何时为空,我不能让strtok
忽略多个选项卡,因为结构取决于计算的17个选项卡,如果字段为空则使用占位符。
我尝试用
解决问题if(tok == NULL || '')
但我不认为strtok
会在标签后识别标签。处理这个问题的最佳方法是什么?
答案 0 :(得分:2)
你不能在你的情况下使用strtok。
来自man strtok:
strtok()函数将字符串分解为零或更多的序列 非空的令牌 ... 从以上描述中可以得出两个或更多个序列 解析后的字符串中的连续分隔符字节被认为是a 单个分隔符,以及在开头或结尾处的分隔符字节 字符串被忽略。换句话说:strtok()返回的令牌 总是非空的字符串。因此,例如,给定字符串 “aaa ;; bbb,”,连续调用strtok()指定分隔符 string“;”将返回字符串“aaa”和“bbb”,然后返回null 指针
因此,您必须找到替代方案,可以手动编写使用线性搜索的函数和strncpy
,或sscanf
或使用strsep
(如果可用)。后者很可能是我的选择,因为它的目的是取代strtok。
来自man strsep:
引入了strsep()函数作为strtok(3)的替代, 因为后者无法处理空场。但是,strtok(3)con 形式为C89 / C99,因此更便携。
答案 1 :(得分:0)
以下是使用strsep
的解决方案,该解决方案专门用于解决strtok
跳过连续分隔符这一事实:
char *cur, *nxt;
while (fgets(buf, sizeof(buf), fp) != NULL)
{
nxt = buf;
while ((cur = strsep(&nxt, "\t")) != NULL)
{
printf("%s->",cur);
}
}
注意:传递给strsep
的字符串必须是可写的(特别是传递文字字符串不起作用)。它将被strsep
修改(分隔符在连续调用时被NUL字符覆盖)。
答案 2 :(得分:0)
开始消化如何实现这一功能的好方法,下面的功能将会这样做,请阅读。 :
int splitLine(char *buf, char **argv, int max_args)
{
int arg;
/* skip over initial spaces */
while (isspace(*buf)) buf++;
for (arg = 0; arg < max_args
&& *buf != '\0'; arg++) {
argv[arg] = buf;
/* skip past letters in word */
while (*buf != '\0'
&& !isspace(*buf)) {
buf++;
}
/* if not at line's end, mark
* word's end and continue */
if (*buf != '\0') {
*buf = '\0';
buf++;
}
/* skip over extra spaces */
while (isspace(*buf)) buf++;
}
return arg;
}
此功能使用空格分隔符,您可以重新实现使用任何其他分隔符。