C++ 如何在C或C+中编写简单的正则表达式模式匹配函数+;?
这是我今天试卷中的一个问题,函数签名是C++ 如何在C或C+中编写简单的正则表达式模式匹配函数+;?,c++,c,regex,algorithm,C++,C,Regex,Algorithm,这是我今天试卷中的一个问题,函数签名是 int is_match(char* pattern,char* string) 该模式仅限于ASCII字符和量化*和?,因此相对简单是否匹配如果匹配应返回1,否则返回0 如何做到这一点?尝试列出有趣的测试用例: 是否匹配(“虚拟”、“虚拟”)应 返回true 匹配(“dumm?y”、“dummy”)是否应该 返回true 是否匹配(“dum?y”、“dummy”) 应该返回false 是否匹配(“dum*y”、“dummy”)应 返回true 等等 然
int is_match(char* pattern,char* string)
该模式仅限于ASCII字符和量化*
和?
,因此相对简单<代码>是否匹配如果匹配应返回1,否则返回0
如何做到这一点?尝试列出有趣的测试用例: 是否匹配(“虚拟”、“虚拟”)应 返回true 匹配(“dumm?y”、“dummy”)是否应该 返回true 是否匹配(“dum?y”、“dummy”) 应该返回false 是否匹配(“dum*y”、“dummy”)应 返回true 等等
然后看看如何让考试更容易通过,然后是下一个…作弊。使用
#include
没有测试、实际编写或调试它,但这可能会让您开始
for each character in the pattern
if pattern character after the current one is *
// enter * state
while current character from target == current pattern char, and not at end
get next character from target
skip a char from the pattern
else if pattern character after the current one is ?
// enter ? state
if current character from target == current pattern char
get next char from target
skip a char from the pattern
else
// enter character state
if current character from target == current pattern character
get next character from target
else
return false
return true
有关无法提交的解决方案,请参阅。有关如何实现更具可读性的描述,请参阅。解决此问题不需要正则表达式和有限状态机的全部功能。作为替代方案,有一个相对简单的动态规划解决方案 如果可以将子字符串[i..n-1]与子模式模式[j,m-1]匹配,则将match(i,j)设为1,其中n和m分别是字符串和模式的长度。否则,让匹配(i,j)为0 基本情况如下:
- 匹配(n,m)=1,可以将空字符串与空模式匹配
- 匹配(i,m)=0,不能将非空字符串与空模式匹配
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int is_match(char* pattern, char* string)
{
int n = strlen(string);
int m = strlen(pattern);
int i, j;
int **match;
match = (int **) malloc((n + 1) * sizeof(int *));
for(i = 0; i <= n; i++) {
match[i] = (int *) malloc((m + 1) * sizeof(int));
}
for(i = n; i >= 0; i--) {
for(j = m; j >= 0; j--) {
if(i == n && j == m) {
match[i][j] = 1;
}
else if(i < n && j == m) {
match[i][j] = 0;
}
else {
match[i][j] = 0;
if(pattern[j + 1] == '*') {
if(match[i][j + 2]) match[i][j] = 1;
if(i < n && pattern[j] == string[i] && match[i + 1][j]) match[i][j] = 1;
}
else if(pattern[j + 1] == '?') {
if(match[i][j + 2]) match[i][j] = 1;
if(i < n && pattern[j] == string[i] && match[i + 1][j + 2]) match[i][j] = 1;
}
else if(i < n && pattern[j] == string[i] && match[i + 1][j + 1]) {
match[i][j] = 1;
}
}
}
}
int result = match[0][0];
for(i = 0; i <= n; i++) {
free(match[i]);
}
free(match);
return result;
}
int main(void)
{
printf("is_match(dummy, dummy) = %d\n", is_match("dummy","dummy"));
printf("is_match(dumm?y, dummy) = %d\n", is_match("dumm?y","dummy"));
printf("is_match(dum?y, dummy) = %d\n", is_match("dum?y","dummy"));
printf("is_match(dum*y, dummy) = %d\n", is_match("dum*y","dummy"));
system("pause");
return 0;
}
#包括
#包括
#包括
int是_匹配(字符*模式,字符*字符串)
{
int n=strlen(字符串);
int m=strlen(模式);
int i,j;
整数**匹配;
match=(int**)malloc((n+1)*sizeof(int*);
对于(i=0;i=0;i--){
对于(j=m;j>=0;j--){
如果(i==n&&j==m){
匹配[i][j]=1;
}
else如果(i 对于(i=0;i,这里是递归可扩展实现。测试模式复杂性的一阶
#include <string.h>
#include <string>
#include <vector>
#include <iostream>
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<Match *> 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<string> 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;
}
#包括
#包括
#包括
#包括
结构匹配{
Match():_next(0){}
虚拟布尔匹配(常量字符*模式,常量字符*输入)常量{
return!std::strcmp(模式,输入);
}
bool next(常量字符*模式,常量字符*输入)常量{
如果(!\u next)返回false;
返回下一步->匹配(模式,输入);
}
常数匹配*\u下一步;
};
类匹配集:公共匹配{
typedef std::向量集;
置零;
公众:
虚拟布尔匹配(常量字符*模式,常量字符*输入)常量{
for(Set::const_迭代器i=toTry.begin();i!=toTry.end();++i){
if((*i)->match(pattern,input))返回true;
}
返回false;
}
无效添加(匹配*m){
总压回(m);
m->_next=这个;
}
~MatchSet(){
for(Set::const_迭代器i=toTry.begin();i!=toTry.end();++i)
如果((*i)->\u next=this)(*i)->\u next=0;
}
};
结构匹配问题:公共匹配{
虚拟布尔匹配(常量字符*模式,常量字符*输入)常量{
如果(模式[0]!='?')
返回false;
if(下一个(模式+1,输入))
返回true;
if(下一个(模式+1,输入+1))
返回true;
返回false;
}
};
结构匹配空:公共匹配{
虚拟布尔匹配(常量字符*模式,常量字符*输入)常量{
if(模式[0]==0&&input[0]==0)
返回true;
返回false;
}
};
结构匹配星号:公共匹配{
虚拟布尔匹配(常量字符*模式,常量字符*输入)常量{
如果(模式[0]!=“*”)
返回false;
如果(模式[1]==0){
返回true;
}
用于(输入i=0;输入[i]!=0;++i){
if(下一个(模式+1,输入+i))
返回true;
}
返回false;
}
};
结构匹配符号:公共匹配{
虚拟布尔匹配(常量字符*模式,常量字符*输入)常量{
/todo:考虑循环以防止不必要的递归
//循环应该检测特殊字符并调用下一个字符
//当前的实现就是从中抽象出来的
如果(模式[0]!=输入[0])
返回false;
返回下一个(模式+1,输入+1);
}
};
类DefaultMatch:公共匹配集{
火柴空了;
匹配问题;
匹配星号;
匹配符号;
公众:
DefaultMatch(){
添加(&空);
添加(&问题);
添加(&星号);
添加(&symbol);
}
无效测试(常量字符*p,常量字符*输入)常量{
testOneWay(p,输入);
如果(!std::strcmp(p,input))返回;
testOneWay(输入,p);
}
bool testOneWay(const char*p,const char*input)const{
常量字符*eqStr=“=”;
bool rv=匹配(p,输入);
如果(!rv)eqStr=“!=”;
std::cout简单的递归实现。它速度慢但易于理解:
int is_match(char *pattern, char *string)
{
if (!pattern[0]) {
return !string[0];
} else if (pattern[1] == '?') {
return (pattern[0] == string[0] && is_match(pattern+2, string+1))
|| is_match(pattern+2, string);
} else if (pattern[1] == '*') {
size_t i;
for (i=0; string[i] == pattern[0]; i++)
if (is_match(pattern+2, string+i)) return 1;
return 0;
} else {
return pattern[0] == string[0] && is_match(pattern+1, string+1);
}
}
希望我没弄错。提供了一篇短文,作为他们正在编写的一本书的演示程序。这篇文章是一篇非常好的阅读,解释了一些代码和正则表达式
我已经使用了这段代码,对一些扩展进行了一些修改,例如对r
c matches any literal character c
. matches any single character
^ matches the beginning of the input string
$ matches the end of the input string
* matches zero or more occurrences of the previous character
/* match: search for regexp anywhere in text */
int match(char *regexp, char *text)
{
if (regexp[0] == '^')
return matchhere(regexp+1, text);
do { /* must look even if string is empty */
if (matchhere(regexp, text))
return 1;
} while (*text++ != '\0');
return 0;
}
/* matchhere: search for regexp at beginning of text */
int matchhere(char *regexp, char *text)
{
if (regexp[0] == '\0')
return 1;
if (regexp[1] == '*')
return matchstar(regexp[0], regexp+2, text);
if (regexp[0] == '$' && regexp[1] == '\0')
return *text == '\0';
if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
return matchhere(regexp+1, text+1);
return 0;
}
/* matchstar: search for c*regexp at beginning of text */
int matchstar(int c, char *regexp, char *text)
{
do { /* a * matches zero or more instances */
if (matchhere(regexp, text))
return 1;
} while (*text != '\0' && (*text++ == c || c == '.'));
return 0;
}
#include<stdio.h>
int mystrstr (const char *,const char *);
int mystrcmp(char *,char *);
int main()
{
char *s1,*s2;//enter the strings, s1 is main string and s2 is substring.
printf("Index is %d\n",mystrstr(s1,s2));
//print the index of the string if string is found
}
//search for the sub-string in the main string
int mystrstr (const char *ps1,const char *ps2)
{
int i=0,j=0,c=0,l,m;char *x,*y;
x=ps1;
y=ps2;
while(*ps1++)i++;
while(*ps2++)j++;
ps1=x;
ps2=y;
char z[j];
for(l=0;l<i-j;l++)
{
for(m=l;m<j+l;m++)
//store the sub-string of similar size from main string
z[c++]=ps1[m];
z[c]='\0'
c=0;
if(mystrcmp(z,ps2)==0)
break;
}
return l;
}
int mystrcmp(char *ps3,char *ps4) //compare two strings
{
int i=0;char *x,*y;
x=ps3;y=ps4;
while((*ps3!=0)&&(*ps3++==*ps4++))i++;
ps3=x;ps4=y;
if(ps3[i]==ps4[i])
return 0;
if(ps3[i]>ps4[i])
return +1;
else
return -1;
}