【问题标题】:checking if a string with asterisk(*) is present within another string检查带有星号(*)的字符串是否存在于另一个字符串中
【发布时间】:2013-06-09 11:55:11
【问题描述】:

我正在开发一个程序来检查给定字符串中是否存在特定字符串:即一个字符串是否是另一个字符串的子字符串。

例如:

1)字符串:YoungPeople --> 要检查的子字符串:ungPeo

  The output should return true.

2)String:你好,你好吗? --> 要检查的子字符串:l*are

    The output should return true.

我使用了基于朴素的搜索算法,它对于第一个输入非常有效。

但我在第二种输入中遇到了问题,其中星号 (*) 应被视为正则表达式:即匹配零个或多个字符。

我应该如何检查带有 * 符号的子字符串?

我应该尝试使用相同的简单算法来搜索 * 之前的字符和之后的字符串吗?或者有没有更好的方法来解决这个问题?

【问题讨论】:

  • 您已经提供了一个很好的方法。试试看有没有问题。
  • 我认为这不是一项简单的任务。您应该检查两种可能性 - 您正在阅读 * 或具体文本。最好的方法是使用实​​际的正则表达式库。
  • strchr 不适合你?
  • 你的意思是通配符吗? Windows API PathMatchSpec() 可以做到这一点,或者在 linux 上使用 fnmatch()
  • 这看起来更像是全局模式匹配而不是正则表达式。

标签: c algorithm search


【解决方案1】:

我应该如何检查带有 * 符号的子字符串?

阅读*后,您需要尝试下面的1-2。

...使用相同的朴素算法进行搜索...有没有更好的方法...?*

有更好的方法。一个递归跟随。

[编辑说明:6/10 发现/修复错误]

当您遍历字符串时,使用递归来检查字符串的其余部分。
* simple 允许 2 个候选路径:
1) 推进str
2) 推进substr
否则,匹配的 char 允许同时推进两者。

// StarCompare() helper function
bool StarCmp(const char *str, const char *pat) {
  if (*pat == '\0') return 1;
  if (*pat == '*') {
    if (*str) {
      // advance str and use the * again
      if (StarCmp(str + 1, pat)) return 1;
    }
    // let * match nothing and advacne to the next pattern
    return StarCmp(str, pat + 1);
  }
  if (*pat == *str) {
    return StarCmp(str + 1, pat + 1);
    }
  return 0;
}  

bool StarCompare(const char *str, const char *pat) {
  if (!str || !pat) return 0;
  do {
    if (StarCmp(str, pat)) return 1;
  } while (*str++);
  return 0;
  }

[编辑以前版本的测试代码]

【讨论】:

    【解决方案2】:

    GNU Regex Library 看起来就是您要找的东西。如果您不熟悉正则表达式,请查看this site

    【讨论】:

    • 可能有点矫枉过正——fnmatch(3) 似乎是一个更好的选择。
    【解决方案3】:

    这是你必须做的:

    1. 用 * 字符分割搜索字符串
    2. 在您正在搜索的字符串中查找每个部分(以正确的顺序)

    或者,您可以按照其他人的建议使用正则表达式。

    【讨论】:

      【解决方案4】:

      寻找编写良好的全局匹配实现的好地方是 bash 源。但这是一个有效的简单递归实现:

      #include <assert.h>
      
      int
      _glob_match(char * pattern, char * str)
      {
        if (!*pattern)          return 1;
        if (!*str)              return 0;
        if (*pattern == '*')    return match_any_tail(pattern + 1, str);
        if (*pattern != *str)   return 0;
        else                    return _glob_match(pattern + 1, str + 1);
      }
      
      int
      match_any_tail(char * pattern, char * str)
      {
        for (; *str; str++)
          if (_glob_match(pattern, str))
            return 1;
        return 0;
      }
      
      int glob_match(char * pattern, char * str)
      {
        return match_any_tail (pattern, str);
      }
      
      void
      main()
      {
        assert(glob_match("ungPeo", "YoungPeople"));
        assert(glob_match("l*are",  "Hello How are You?"));
      }
      

      【讨论】:

      • 不,那会让模式“abc”匹配字符串“abbc”。
      • @chux 你对“abc”、“abbc”的情况是完全正确的——谢谢。事实证明,如果您将 *pattern != *str 更改为失败,那么 match_any_tail 会针对这种情况和问题中的两个提供正确的全局匹配行为。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-24
      • 2019-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多