8

strtok()在 c 中使用来解析 csv 字符串。首先,我对其进行标记以找出有多少标记,以便分配正确大小的字符串。然后我使用上次用于标记化的相同变量。每次我第二次执行它时,它strtok(NULL, ",")都会返回NULL,即使还有更多的标记要解析。有人可以告诉我我做错了什么吗?

char* tok;
int count = 0;
tok = strtok(buffer, ",");
while(tok != NULL) {
    count++;
    tok = strtok(NULL, ",");
}

//allocate array

tok = strtok(buffer, ",");
while(tok != NULL) {
    //do other stuff
    tok = strtok(NULL, ",");
}

因此,在第二个 while 循环中,它总是在找到第一个标记后结束,即使有更多标记也是如此。有人知道我做错了什么吗?

4

3 回答 3

18

strtok()修改它所操作的字符串,用空值替换分隔符。因此,如果您想多次使用它,则必须制作一份副本。

于 2010-12-28T06:13:45.197 回答
2

不一定需要复制 -strtok()确实修改了它正在标记的字符串,但在大多数情况下,这只是意味着如果您想再次处理标记,字符串已经被标记。

这是您的程序在第一次通过后进行了一些修改以处理令牌:

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

int main()
{
    int i;
    char buffer[] = "some, string with  ,  tokens";

    char* tok;
    int count = 0;
    tok = strtok(buffer, ",");
    while(tok != NULL) {
        count++;
        tok = strtok(NULL, ",");
    }


    // walk through the tokenized buffer again
    tok = buffer;

    for (i = 0; i < count; ++i) {
        printf( "token %d: \"%s\"\n", i+1, tok);
        tok += strlen(tok) + 1;  // get the next token by skipping past the '\0'
        tok += strspn(tok, ","); //   then skipping any starting delimiters
    }

     return 0;
  }

请注意,不幸的是,这比我第一次发布的要棘手 -strspn()需要在跳过放置的 '\0' 之后执行调用,strtok()因为strtok()将跳过它返回的标记的任何前导分隔符(不替换源中的分隔符)。

于 2010-12-28T07:17:03.577 回答
2

使用 strsep - 它实际上会更新您的指针。在您的情况下,您将不得不继续调用 NULL 而不是传入字符串的地址。strsep 的唯一问题是,如果它以前是在堆上分配的,请保留一个指向开头的指针,然后再释放它。

char *strsep(char **string, char *delim);

字符 *字符串;字符 * 令牌;令牌 = strsep(&string, ",");

strtok 用于 C 课程的正常介绍 - 使用 strsep,它会好得多。:-) 不要对“哦该死 - 我必须传递 NULL 仍然因为 strtok 搞砸了我的定位”感到困惑。

于 2011-01-01T21:35:44.457 回答