在C中拆分字符串以识别连续的标签

时间:2016-03-30 20:31:40

标签: 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) {
        printf("%s->",tok);
        tok = strtok(NULL,"\t");
    }
}

我获得了所有令牌,但忽略了双标签\t\t或更多。但是,我需要知道字段何时为空,我不能让strtok忽略多个选项卡,因为结构取决于计算的17个选项卡,如果字段为空则使用占位符。

我尝试用

解决问题
if(tok == NULL || '')

但我不认为strtok会在标签后识别标签。处理这个问题的最佳方法是什么?

3 个答案:

答案 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;
}

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