需要关于strtok功能的想法?

时间:2011-04-20 07:10:24

标签: c strtok

朋友们,我正在从文件中读取数据并借助','来分隔值。 输入文件:

shankar,kumar,ooty
ravi,,cbe

代码:

while ( fgets ( mem_buf, sizeof mem_buf, infile ) != NULL ) 
{
item = strtok(mem_buf,delims); 
printf("1 val:%s",item);    
item = strtok(NULL,delims);    
printf("2 val:%s",item);    
item = strtok(NULL,delims);    
printf("3 val:%s",item);
}

对于上面的输入文件输出如:

1:shankar 2:kumar 3:ooty
1:ravi 2:cbe 3:

但我需要输出,

1:shankar 2:kumar 3:ooty
1:ravi 2: 3:cbe 

因为在第二行的输入文件中,中间数据为空?你能帮帮我吗? 我知道这是因为在第二行输入文件之间没有空格吗?请告诉我任何其他替代方法?或者我应该在读取之前更改输入文件?

5 个答案:

答案 0 :(得分:3)

没有什么可以阻止您编写自己的 strtok - 就像函数一样:

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

static char *myStrTok (char *s, int c) {
    static char *nextS = NULL;  // Holds modified delimiter.
    static int done = 1;        // Flag to indicate all done.

    // Initial case.
    if (s != NULL) {
        // Return NULL for empty string.
        if (*s == '\0') { done = 1; return NULL; }

        // Find next delimiter.
        nextS = s;
        while ((*nextS != c) && (*nextS != '\0')) nextS++;
        done = (*nextS == '\0');
        *nextS = '\0';
        return s;
    }

    // Subsequent cases.
    if (done) return NULL;

    // Put delimiter back and find next one.
    *nextS++ = c;
    s = nextS;
    while ((*nextS != c) && (*nextS != '\0')) nextS++;
    done = (*nextS == '\0');
    *nextS = '\0';
    return s;
}

static int prt (char *s) {
    char *s2 = myStrTok (s, ','); printf ("1: [%s]\n", s2);
    s2 = myStrTok (NULL, ',');    printf ("2: [%s]\n", s2);
    s2 = myStrTok (NULL, ',');    printf ("3: [%s]\n", s2);
    s2 = myStrTok (NULL, ',');    if (s2 != NULL) printf ("4: [%s]\n", s2);
    printf ("==========\n");
}

int main (void) {
    char x[] = "shankar,kumar,ooty"; char y[] = "ravi,,cbe";
    prt (x); prt (y);
    printf ("[%s] [%s]\n", x, y);
    return 0;
}

输出:

1: [shankar]
2: [kumar]
3: [ooty]
==========
1: [ravi]
2: []
3: [cbe]
==========
[shankar,kumar,ooty] [ravi,,cbe]

如你所愿。它只处理分隔符的单个字符,但在这种情况下似乎足够了。

答案 1 :(得分:2)

从联机帮助页:“一个包含两个或多个连续分隔符的序列        解析的字符串被认为是单个分隔符。字符串开头或结尾的分隔符字符将被忽略。换一个        方式:strtok()返回的标记总是非空字符串。“

因此,如果你必须使用strtok,你将不得不以某种方式修改输入。

答案 2 :(得分:0)

您可以检查每个item的长度,以确保它不是0.

更好的是,将它与循环每一行(example)结合起来,这样你就不会受限于三个值。

答案 3 :(得分:0)

如果strtok无法完成您想要的工作,您可以对自己的解析器进行编码,类似于以下内容:

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

static int prt (char *s) {
    char *s2;
    s2 = strchr (s, ','); printf ("1: [%*.*s]\n", s2-s, s2-s, s); s = s2 + 1;
    s2 = strchr (s, ','); printf ("2: [%*.*s]\n", s2-s, s2-s, s); s = s2 + 1;
    printf ("3: [%s]\n", s);
    printf ("==========\n");
}

int main (void) {
    char x[] = "shankar,kumar,ooty"; char y[] = "ravi,,cbe";
    prt (x2); prt (y2);
    return 0;
}

该小样本显示了strtok解决方案与手动strchr解决方案之间的区别,输出为:

1: [shankar]
2: [kumar]
3: [ooty]
==========
1: [ravi]
2: []
3: [cbe]
==========

您需要注意没有足够分隔符(或太多分隔符)的情况,但这应该是一个小修改。

答案 4 :(得分:0)

这是我从Rob Pike无耻地复制的一种技术:

void print_tokens(char *s)
{
    char *p, *last;

    last = s;

    for (p = strchr(s, ','); p; p=strchr(p+1, ',')){
            *p = 0;
            puts(last);
            *p = ',';
            last = p+1;
    }
    puts(last);
}

我没有测试上面的代码,因此可能存在一些小缺陷。不过,主要的想法应该是清楚的。