strtok() 在不应该返回 null 时返回 null

strtok() returning null when it shouldn´t

提问人:FGomes 提问时间:7/15/2023 更新时间:7/15/2023 访问量:62

问:

我制作了一个接收字符串的函数,它应该在“-e”之后返回元素。例如,“show -e LENA”应返回“LENA”。

char *getElementAfterE(char *str) {
  const char *delimiter = " ";
  const char *flag = "-e";
  char *result = NULL;

  char *token = strtok(str, delimiter); // Get the first token

  while (token != NULL) {
    if (strcmp(token, flag) == 0) {
      token = strtok(NULL, delimiter); // Get the next token
      printf("next token: %s\n", token);
      if (token != NULL) {
        result = token;
      }
      break;
    }

    token = strtok(NULL, delimiter); // Get the next token
  }
  return result;
}

问题是 if allways 之后的 strtok 返回 null,即使字符串仍有剩余的标记。

显然,它与我给函数的字符串有关。 如果我使用指针,它不起作用:

char *str = "show -e LENA";
char *result = getElementAfterE(str);

如果我使用 char 数组,它可以工作:

char str[] = "show -e LENA";
char *result = getElementAfterE(str);

问题是在我的程序中,我给它一个指针。在将指针提供给函数之前,我是否需要将指针复制到 char 数组中?

数组 C strtok

评论


答:

4赞 ikegami 7/15/2023 #1

strtok修改提供的字符串。它基本上将分隔符替换为 NULL,以便创建一个适当的字符串来返回,而无需分配任何内存。

您正在传递一个字符串文本。修改字符串文本是未定义的行为。

改用 会创建一个可修改的数组。char str[] = "show -e LENA";

字符串不需要在数组中,但它确实需要可修改。

3赞 John Bollinger 7/15/2023 #2

如果我使用指针,它不起作用 [,但是] 如果我使用 char 数组,它会起作用

这与指针与指针无关。数组。这是关于可修改的对象。不可修改的。

strtok()在工作时修改源字符串,并且它返回的令牌与原始字符串共享存储。当您提供给它的源指针派生自 类型 的声明数组时,这工作正常。它也可以很好地与指向存储在动态分配空间中的字符串的指针一起使用。原则上,它使用指向任何可修改对象的表示形式的指针,该对象的表示形式包含空字节。char

但是由于历史原因,即使字符串文字表示 (non-) 的数组,程序也被禁止尝试修改它们。这意味着指向字符串文本的指针 (in) 不是可接受的第一个参数,即使它可能是正确的类型。试图以这种方式使用一个会唤起未定义的行为,并且您已经观察到了这种影响。constcharstrtok()

为了避免此类问题,避免将字符串文本与指向 的指针相关联会有所帮助。相反,请将它们与指向以下内容的指针相关联:charconst char

const char *str = "show -e LENA";

这可以更好地反映实际语义,并且它将帮助您的编译器帮助您检测字符串文字的误用。

在将指针提供给函数之前,我是否需要将指针复制到 char 数组中?

如果您收到要解析为字符串文字的字符串,并且想要通过 解析内容,那么是的,您需要先将它们复制到声明或动态分配的数组中。这同样适用于 的数组。strtok()const char