【问题标题】:strtok not working as expectedstrtok 没有按预期工作
【发布时间】:2012-12-25 12:04:10
【问题描述】:

我尝试编写一个函数,该函数获取一个指向 char 数组的指针,从用户那里读取一个字符串并删除字符串开头的所有空格,直到第一个不是字符串的字符出现。最后返回开头没有空格的字符串副本。

例如,

对于输入abcd,函数应该返回指向字符串abcd的指针。

对于输入123 123,函数应该返回指向字符串123 123的指针。

功能如下图,

void read_RemoveSpace(char * str)/**read the rest of string**/
{
    char tempRead[30];
    fgets(tempRead,30,stdin);
    char *ptr = strtok(tempRead, " "); /**remove spaces between command and other data**/
    strcpy(str,ptr); /**copy the new string without the spaces.**/
}

但由于某些原因,函数 strtok() 没有按预期工作。

输入时:

   123 456

该函数只返回没有空格的第一部分,而不是字符串的其余部分,即它指向

123

有什么建议吗?

【问题讨论】:

  • 您面临的问题是什么?您是如何调用函数的?调用后 str 中究竟存储了什么?
  • strtok_r() 确实按预期工作,也许只是您的期望不正确......

标签: c strtok


【解决方案1】:

strtok 工作正常。它将输入分成字符串123456

strtok (tempRead, " "); /* Returns 123 */
strtok (NULL, " "); /* Returns 456 */

我认为您可以使用更简单的解决方案:

int i = 0;
char tempRead[30];
...
while (tempRead[i] == ' ' && tempRead[i])
  i++;
strcpy(str,tempRead+i);

【讨论】:

    【解决方案2】:

    它完全按预期工作。

    第一次调用 strtok 将返回第一次出现的标记;只要您将第一个参数提供为 NULL,后续调用将一次返回一个其余令牌;并且 strtok 将在令牌用完时返回 NULL。

    编辑:
    有些事情可能会导致奇怪的错误,所以我在这里引用手册页中提到的内容以及使用 strtok 时应始终牢记的内容:

    使用这些功能时要小心。如果您确实使用它们,请注意 那:

    • 这些函数修改它们的第一个参数。

    • 这些函数不能用于常量字符串。

    • 分隔符的标识丢失。

    • strtok() 函数在解析时使用静态缓冲区,所以它不是 线程安全。如果这对您很重要,请使用 strtok_r()

    【讨论】:

      【解决方案3】:

      使用strtok() 并不是显而易见的方法。

      void read_RemoveSpace(char *str)
      {
          char *dst = str;
          char tempRead[30];
          if (fgets(tempRead, sizeof(tempRead), stdin) != 0)
          {
              char *src = tempRead;
              char c;
              while ((c = *src++) != '\0')
              {
                  if (c != ' ')
                      *dst++ = c;
              }
          }
          *dst = '\0';
      }
      

      这会将tempRead 中的非空格复制到str,包括换行符;如果您愿意,可以使用#include <ctype.h> 中的isspace()isblank()。我不相信 30 对于本地字符串来说是一个很好的长度,但这就是您在问题中所遇到的。可以说,您应该指定接口中提供的字符串大小:void *read_RemoveSpace(char *buffer, size_t buflen)。您还可以让函数返回指向字符串末尾的 null 的指针(从而间接给出字符串的长度减去空格)。

      void read_RemoveSpace(char *buffer, size_t buflen)
      {
          char *dst = buffer;
          char tempRead[buflen];
          if (fgets(tempRead, sizeof(tempRead), stdin) != 0)
          {
              char *src = tempRead;
              char c;
              while ((c = *src++) != '\0')
              {
                  if (!isspace((unsigned char)c))
                      *dst++ = c;
              }
          }
          *dst = '\0';
          return dst;
      }
      

      没有太大不同,但更安全。它使用本地 VLA(可变长度数组),它是 C99 的一部分。可以放弃 VLA 并直接复制到目标缓冲区:

      void read_RemoveSpace(char *buffer, size_t buflen)
      {
          char *dst = buffer;
          if (fgets(buffer, buflen, stdin) != 0)
          {
              char *src = buffer;
              char c;
              while ((c = *src++) != '\0')
              {
                  if (!isspace((unsigned char)c))
                      *dst++ = c;
              }
          }
          *dst = '\0';
          return dst;
      }
      

      直到第一个空格,这个复制都是空操作;此后,它将字符复制到它们的最终位置。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-19
        • 2020-03-18
        • 2012-06-14
        • 2014-11-15
        • 1970-01-01
        • 2012-07-02
        • 2011-09-07
        • 2013-03-03
        相关资源
        最近更新 更多