strtok中最后一个单词的取用

时间:2018-06-27 21:40:49

标签: c strtok

使用以下行给出文件:

  

word1 word2 word3 word4

我试图编写以下代码:

Exit status is 4

用于打印“单词”。

正在工作。但是,我什么都不懂。

最后一个单词FILE* f = fopen("my_file.txt", "r"); char line[MAX_BUFFER + 1]; if (fgets(line, MAX_LENGTH_LINE, f) == NULL) { return NULL; } char* word = strtok(line, " "); for (int i = 0; i < 4; i++) { printf("%s ", word); word = strtok(NULL, " "); } 的效果如何? (我不明白,因为在“ word4”之后不存在空格。)。

2 个答案:

答案 0 :(得分:2)

我不太确定您要问什么。您是在问程序即使没有空格也能从文件中正确读取word4吗?或者您是在问为什么,当程序退回打印word4时,似乎没有在其后打印空格?

第一个问题的答案是strtok旨在为您提供以分隔符分隔的标记,而不是由分隔符终止的标记。不需要在最后一个标记后跟定界符。

要查看第二个问题的答案,如果稍稍调整程序及其打印输出,可能会更清楚:

char* word = strtok(line, " ");
for (int i = 0; word != NULL; i++) {
    printf("%d: \"%s\"\n", i, word);
    word = strtok(NULL, " ");
}

我在这里做了两项更改:

  1. 循环运行直到word为NULL为止,也就是说,只要strtok在行上找到另一个单词。 (这是为了确保我们看到 all 个单词,并确保我们不试图以任何方式特别对待第四个单词。如果您 以某种方式特别对待第四个单词,请这样说。)
  2. 将单词打印出来,并用引号引起来,以便我们可以准确看到它们包含的内容。

运行修改后的程序时,我看到:

0: "word1"
1: "word2"
2: "word3"
3: "word4
"

最后一行最初看起来很奇怪,但是解释很简单。您最初使用fgets读取该行,该行确实将终止的\n字符复制到line缓冲区中。因此,它最终停留在word4上;也就是说,第四个“单词”是"word4\n"

基于这个原因,通常建议将\n包含在您要交给strtok的空白定界符中,也就是说,可以调用strtok(line, " \n")。如果我这样做(在两个strtok调用中),输出将更改为

0: "word1"
1: "word2"
2: "word3"
3: "word4"

可能更接近您的预期。

答案 1 :(得分:0)

您的代码不检查strtok()的返回值,在某些情况下可能不安全。

/*  Split string
    @content origin string content
    @delim   delimiter for splitting
    @psize   pointer pointing at the variable to store token size
    @return  tokens after splitting
 */
const char **split(char *content, const char *delim, int *psize)
{
    char *token;
    const char **tokens;
    int capacity;
    int size = 0;

    token = strtok(content, delim);
    if (!token)
    {
        return NULL;
    }

    // Initialize tokens
    tokens = malloc(sizeof(char *) * 64);
    if (!tokens)
    {
        exit(-1);
    }
    capacity = 64;

    tokens[size++] = token;

    while ((token = strtok(NULL, delim)))
    {
        if (size >= capacity)
        {
            tokens = realloc(tokens, sizeof(char *) * capacity * 2);
            if (!tokens)
            {
                exit(-1);
            }
            capacity *= 2;
        }
        tokens[size++] = token;
    }

    // if (size < capacity)
    // {
    //  tokens = realloc(tokens, sizeof(char *) * size);
    //  if (!tokens)
    //  {
    //      exit(-1);
    //  }
    // }
    *psize = size;

    return tokens;
}