How do I write a simple regular expression pattern matching function in C or C++?

后端 未结 9 962
我寻月下人不归
我寻月下人不归 2021-02-01 06:58

This is a question in my paper test today, the function signature is

int is_match(char* pattern,char* string)

The pattern is limited to only A

9条回答
  •  庸人自扰
    2021-02-01 07:35

    Here is recursive extendable implementation. Tested for first order of pattern complexity.

    #include 
    #include 
    #include 
    #include 
    
    struct Match {
      Match():_next(0) {}
      virtual bool match(const char * pattern, const char * input) const {
        return !std::strcmp(pattern, input);
      }
      bool next(const char * pattern, const char * input) const {
        if (!_next) return false;
        return _next->match(pattern, input);
      }
      const Match * _next;
    };
    
    class MatchSet: public Match {
      typedef std::vector Set;
      Set toTry;
    public:
      virtual bool match(const char * pattern, const char * input) const {
        for (Set::const_iterator i = toTry.begin(); i !=toTry.end(); ++i) {
          if ((*i)->match(pattern, input)) return true;
        }
        return false;
      }
      void add(Match * m) {
        toTry.push_back(m);
        m->_next = this;
      }
      ~MatchSet() {
        for (Set::const_iterator i = toTry.begin(); i !=toTry.end(); ++i)
          if ((*i)->_next==this) (*i)->_next = 0;
      }
    };
    
    struct MatchQuestion: public Match  {
      virtual bool match(const char * pattern, const char * input) const {
        if (pattern[0] != '?')
          return false;
        if (next(pattern+1, input))
          return true;
        if (next(pattern+1, input+1))
          return true;
        return false;
      }
    };
    
    struct MatchEmpty: public Match {
      virtual bool match(const char * pattern, const char * input) const {
        if (pattern[0]==0 && input[0]==0)
          return true;
        return false;
      }
    };
    
    struct MatchAsterisk: public Match {
      virtual bool match(const char * pattern, const char * input) const {
        if (pattern[0] != '*')
          return false;
        if (pattern[1] == 0) {
          return true;
        }
        for (int i = 0; input[i] != 0; ++i) {
          if (next(pattern+1, input+i))
            return true;
        }
        return false;
      }
    };
    
    struct MatchSymbol: public Match {
      virtual bool match(const char * pattern, const char * input) const {
        // TODO: consider cycle here to prevent unnecessary recursion
        // Cycle should detect special characters and call next on them
        // Current implementation abstracts from that
        if (pattern[0] != input[0])
          return false;
        return next(pattern+1, input+1);
      }
    };
    
    class DefaultMatch: public MatchSet {
      MatchEmpty empty;
      MatchQuestion question;
      MatchAsterisk asterisk;
      MatchSymbol symbol;
    public:
      DefaultMatch() {
        add(&empty);
        add(&question);
        add(&asterisk);
        add(&symbol);
      }
      void test(const char * p, const char * input) const {
        testOneWay(p, input);
        if (!std::strcmp(p, input)) return;
        testOneWay(input, p);
      }
      bool testOneWay(const char * p, const char * input) const {
        const char * eqStr = " == ";
        bool rv = match(p, input);
        if (!rv) eqStr = " != ";
        std::cout << p << eqStr << input << std::endl;
        return rv;
      }
    
    };
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
      using namespace std;
    
      typedef vector Strings;
      Strings patterns;
    
      patterns.push_back("*");
      patterns.push_back("*hw");
      patterns.push_back("h*w");
      patterns.push_back("hw*");
    
      patterns.push_back("?");
      patterns.push_back("?ab");
      patterns.push_back("a?b");
      patterns.push_back("ab?");
    
      patterns.push_back("c");
      patterns.push_back("cab");
      patterns.push_back("acb");
      patterns.push_back("abc");
    
      patterns.push_back("*this homework?");
      patterns.push_back("Is this homework?");
      patterns.push_back("This is homework!");
      patterns.push_back("How is this homework?");
    
      patterns.push_back("hw");
      patterns.push_back("homework");
      patterns.push_back("howork");
    
      DefaultMatch d;
      for (unsigned i = 0; i < patterns.size(); ++i)
        for (unsigned j =i; j < patterns.size(); ++j)
          d.test(patterns[i].c_str(), patterns[j].c_str());
    
        return 0;
    }
    

    If something is unclear, ask.

提交回复
热议问题