【问题标题】:Using strtok to find substring使用 strtok 查找子字符串
【发布时间】:2015-04-16 07:05:46
【问题描述】:

我有一串很多字母

string path = "cxzaserds";

还有一个目标词

string word = "cars";

在我的函数match() 中,如果在路径中(按顺序)找到来自word 的字符,我想返回true,在这种情况下,它将返回true('c' 出现在'a' 之前'在path 字符串中,r' 位于 's' 之前)。

我正在尝试使用strtok() 逐个查找每个字符,分隔符是当前索引的字母。

我的进步:

bool match (string path, string word)
{
  char * cstr = new char [path.length()+1]; //workaround for strtok on string
  std::strcpy (cstr, path.c_str());

    char *p;

  for (int i = 0 ; i < path.length(); i++)
    {
    //error here, "invalid conversion from 'char' to 'const char*'
      p = strtok (cstr, word[i]);

      if (p != NULL) //if strtok found word[i]
        continue;
      else return false; //was NULL, word not found
    }

  return true; //made it through, return true
}

在 C++ 页面的分隔符下,它说:

这些可能与一个调用不同。

http://www.cplusplus.com/reference/cstring/strtok/

当 strtok 返回非 null 时,我可以做些什么来更改分隔符? 或者完全是另一种(更简单的)解决方案?

【问题讨论】:

  • strtok 的第二个参数是 char*,而不是 charword[i]char。这是一个分隔符列表,而不是单个。我会怎么做?放弃 strotk 以支持更多 C++ 风格。 Related post.

标签: c++ strtok


【解决方案1】:

正如 Vlad 所说,您不应该混合使用 STL 代码 (std::string) 和经典 c 代码 (strtok())。

相反,您可以使用 std::string 成员,例如 find()find_first_of() 来解决您的问题:

bool match(const std::string &path, const std::string &word) {
    std::size_t pos = 0; // position of the last match

    // iterate over all characters in 'word'
    for (std::size_t i = 0; i < word.length(); ++i) {
        // look for the next character and store the new position
        if ((pos = path.find(word[i], pos)) == std::string::npos)
            return false; // return false if it couldn't be found
    }
    return true; // all characters have been found in order
}

【讨论】:

    【解决方案2】:

    你写过:

    p = strtok(cstr, word[i]);
    

    作为第二个参数,您将传递ith 字符(其类型为char)。

    但是,正如文档所述,第二个参数必须是 const char * 类型,这意味着它是一个分隔符数组。所以你有一个类型不匹配。

    最简单的解决方案是创建一个分隔符数组(注意它是NUL-终止的,它实际上是一个只有一个字母的C风格字符串):

    char delimiters[] = { word[i], '\0' };
    

    然后像这样使用它:

    p = strtok(cstr, delimiters);
    

    另一方面,这种方法是非 C++ 风格的,可能在现实生活中你会想要别的东西。

    【讨论】:

    • 为什么投反对票?也许这不是最好的解决方案,但它是有效的并且解决了所描述的问题。
    • 不是我的反对意见,但您使用并非真正为此目的而设计的功能使目标问题过于复杂(因为它做得更多)。
    • 我同意。无论如何,这不是题外话,这可能是@filposs 了解更多 C 类型的好机会,因为他似乎对此有一些困难。我们这里有破坏者吗?其他(甚至更正确)的答案也被否决了。
    【解决方案3】:

    我已经回答了这个问题,所以我不想在这里完全重复。在这里问了这个问题,但我找不到。 不过你可以在my personal forum看到答案

    虽然答案是用俄语写的,但代码是用英文写的。:) 此外,您可以使用网络服务翻译翻译描述。

    至于将标准 C 函数 strtokstd::string 类型的对象一起使用,那简直是个坏主意,不应使用。

    另一种方法是使用标准算法std::all_of和标准C函数strchr

    【讨论】:

      【解决方案4】:

      strchr 在这个问题上比strtok 好很多;实际上正如其他人提到的那样,strtok 的设计确实很糟糕,很难想象在哪些情况下使用它是个好主意。

      strchr 查找 C 字符串中第一次出现的字符。

      这个使用strchr的问题即使在C语言中也变成了单行:

      int match(const char *needle, const char *haystack) {
          while (haystack && *needle) {
              haystack = strchr(haystack, *needle++);
          }
          return haystack != NULL;
      }
      

      【讨论】:

        【解决方案5】:

        鉴于您的问题以及 C/C++ 将允许您使用普通下标来处理单个字符这一事实,那么 strtok 似乎只会使解决方案复杂化。

        类似(未经测试的代码!):

        boolean hasWord ( char * needle, char * haystack) {
           int nlen = strlen(needle);
           int npos = 0;
           int hlen = strlen(haystack);
           int hpos = 0;
           for (hpos = 0 ; hpos < hlen ; hpos++) {
                if (needle[npos] == haystack[hpos]) {
                    // got a match now look for next letter
                    npos++;
                    if (npos >= nlen) {
                        // all letters now matched in sequence
                        return true;
                    }
                }
           }
           return false;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-07
          • 2013-10-22
          相关资源
          最近更新 更多