使用strtok()从字符串中解析标记

时间:2015-04-20 09:05:14

标签: c string parsing strtok

char line[] = "COPY\tSTART\t0\tCOPY";
char *tmp;

tmp = strtok(line, "\t");
printf("%s", tmp);

此代码的输出为COPY。而当

char line[] = "\tSTART\t0\tCOPY";

输出为START

但是!我想检查字符串START前面没有任何内容。 我认为\t是第一个分隔符,因此strtok(line, "\t")的输出为NULL。 但实际输出为START

有任何误解吗?我该怎么办?

2 个答案:

答案 0 :(得分:3)

根据strtok() man page(强调我的)

  

解析后的字符串中的两个或多个连续分隔符字节的序列被视为单个分隔符。 忽略字符串开头或结尾的分隔符字节。换句话说:strtok()返回的标记始终是非空字符串。

所以,您正在经历的是strtok()的正确行为。

OTOH,如果没有更多令牌,strtok()将返回NULL,因此根据您的预期,为初始分隔符返回NULL将传达错误消息,这将令人困惑。所以,底线是,

  • 如果令牌存在

      

    strtok()返回的标记总是非空字符串。

  • 如果令牌不存在

      

    strtok()将返回NULL。

注意:在使用retured 令牌之前提一下,总是检查NULL。

答案 1 :(得分:1)

  

我该怎么办?

构建自己的函数,而不是strtok的工作原理,但你可以得到一些想法:

#include <stdio.h>
#include <string.h>

char *scan(char **pp, char c)
{
    char *s, *p;

    p = strchr(*pp, c);
    if (p) *p++ = '\0';
    s = *pp;
    *pp = p;
    return s;
}

int main(void)
{
    char line1[] = "COPY\tSTART\t0\tCOPY";
    char line2[] = "\tSTART\t0\tCOPY";
    char *p;

    puts("Line 1");
    p = line1;
    while (p) {
        printf("%s\n", scan(&p, '\t'));
    }
    puts("Line 2");
    p = line2;
    while (p) {
        printf("%s\n", scan(&p, '\t'));
    }
    return 0;
}

输出:

Line 1
COPY
START
0
COPY
Line 2

START
0
COPY