用于计算C中两个字符串匹配的次数的函数

时间:2016-02-14 08:20:23

标签: c

我试图找到c中两个字符串匹配的时间,如果我们有两个或更多个星,多个字符串组合可能是合适的。例如"abcdb"& "*b*"匹配两次。我当前的代码有效,但它返回四个。我不知道我在这里缺少什么。

#include <stdio.h>

int nmatch(char *s1, char *s2) {
    if (*s1 != '\0' && *s2 != '\0' && *s2 == '*' && (*s2 + 1) != *s1) {
        return nmatch(s1 + 1, s2) + 1;
    }
    if (*s1 == *s2) {
        return nmatch(s1 + 1, s2 + 1);
    }
    if (*s1 == *s2 && *s1 == '\0' && *s2 == '\0') {
        return 0;
    }
    return (1);
}

int main() {
    char ap[] = "abcd";
    char ab[] = "*b*";
    printf("%d", nmatch(ap, ab));
    return 0;
}

2 个答案:

答案 0 :(得分:1)

您的代码不计算s1匹配模式s2的不同方式的数量。对于相同的字符串,它甚至不返回1.

第一次比较(*s2 + 1) != *s1不正确,您可能认为*(s2 + 1) != *s1等同于s2[1] != *s1,但此修复程序不足以纠正算法。

以下是一个天真的实现:

int nmatch(const char *s1, const char *s2) {
    int count;
    while (*s2 != '\0' && *s2 != '*' && *s1 == *s2) {
        s1++;
        s2++;
    }
    if (*s2 == '\0')
        return *s1 == '\0';
    if (*s2 != '*')
        return 0;
    while (*s2 == '*')    /* skip all stars */
        s2++;
    if (*s2 == '\0')
        return 1;
    for (count = 0;; s1++) {
        count += nmatch(s1, s2);
        if (*s1 == '\0')
            break;
    }
    return count;
}

答案 1 :(得分:0)

我认为你的算法错了。再加上有缺陷的实施,这将无处可去。

输入字符串和模式字符串。如果模式的第一个字符 a *并且不等于输入字符串的第一个字符,则返回0(这是不匹配)。

如果它们相等,则删除输入和模式的第一个字符,并返回缩小的输入和模式的匹配数。

另一方面,如果模式的第一个字符是*,那么(在一个循环中)将剩余模式与完整输入字符串的匹配数相加,输入字符串没有第一个,然后没有第二个字符......依此类推,直到输入字符串为空。

如果输入和模式都为空:返回1.如果只有一个字符串为空:返回0。

我将它实现为直接递归函数(用于生产用途,应该转换为迭代版本):

unsigned matches(char const * const input, char const * const pattern) {
  if (! *pattern) {
    // An empty pattern matches only the empty
    // string, nothing else
    return (*input) ? 0 : 1;
  }
  if (*pattern == '*') {
    // a wildcard could be zero to any number
    // of characters. Sum the number of matches
    // for each possibility (excluding the empty
    // rest of input for now)
    char const * rest = input;
    unsigned count = 0;
    while (*rest) {
      count += matches(rest, pattern + 1);
      ++rest;
    }
    // Add matches for the empty rest of input
    count += matches(rest, pattern + 1);
    return count;
  }
  if (! *input) {
    // A non empty, non wildcard pattern cannot
    // match the empty string
    return 0;
  }
  if (*pattern == *input) {
    // non wildcard match, count the ways the rest of
    // the pattern matches the rest of the input.
    return matches(input + 1, pattern + 1);
  }
  else {
    // mismatch!
    return 0;
  }
}

Live with tests

为了处理模式中存在多个相邻通配符时可能匹配的组合爆炸,可以先从模式中删除这些通配符。