Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中拆分字符串以识别连续的制表符_C_Strtok - Fatal编程技术网

在C中拆分字符串以识别连续的制表符

在C中拆分字符串以识别连续的制表符,c,strtok,C,Strtok,我有一个文件,其中某些字段由选项卡分隔。始终会有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)

我有一个文件,其中某些字段由选项卡分隔。始终会有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能在一个标签之后识别一个标签。处理此问题的最佳方法是什么?

您不能在您的案例中使用strtok。 从
man strtok:

函数的作用是:将字符串分解为零或更多的序列 非空代币 ... 根据以上描述,可以得出两个或更多的序列 已解析字符串中的连续分隔符字节被视为 单个分隔符,并且该分隔符位于 字符串被忽略。换句话说:strtok()返回的令牌 总是非空字符串。因此,例如,给定字符串 “aaa;;bbb”,连续调用strtok()以指定分隔符 字符串“;,”将返回字符串“aaa”和“bbb”,然后返回空值 指针

因此,您必须找到一种替代方法,可以手动编写一个使用线性搜索和
strncpy
的函数,或者
sscanf
或使用
strep
,如果可用的话。后者很可能是我的选择,因为它是用来取代斯特托克的

man strep:

引入strep()函数是为了替换strtok(3), 因为后者不能处理空字段。然而,strtok(3)公司 表单转换为C89/C99,因此更便于携带


下面是一个使用
strep
的解决方案,它的引入是为了解决
strtok
跳过连续分隔符的问题:

char *cur, *nxt;
while (fgets(buf, sizeof(buf), fp) != NULL)
{
    nxt = buf;
    while ((cur = strsep(&nxt, "\t")) != NULL)
    {
        printf("%s->",cur);
    }
}

注意:传递给strep的字符串必须是可写的(传递文本字符串不起作用)。它将被
strep
修改(在连续调用时,分隔符将被NUL字符覆盖)。

这是一个很好的开始理解如何实现这一点的方法,下面的函数将实现这一点,请阅读:

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;
}
int分割线(char*buf,char**argv,int max_args)
{
int-arg;
/*跳过初始空格*/
而(isspace(*buf))buf++;
对于(arg=0;arg

此函数使用空格分隔符,您可以重新实现以使用任何其他分隔符。

观察它-如果(tok==NULL | |“”)
尝试看起来您已经习惯了另一种语言,请查看您的
。它在技术上是有效的C语言,但几乎肯定不是您想要做的。构建一个状态机和/或使用strspn()/strcspn()。下面是
strep()
的一个简单实现,如果它还不是工具链的一部分,您可以使用它: