异或表达式运算

本来要参加中兴的比赛的。可惜没有时间做了。

用法:像正常的表达式一样。

key1 and key2 and key3 如果key1 为false的话,后面的不再计算。

key1 or key2 or key3 如果key1为true,后面的也不用再计算。

支持括号。

查找过滤时 用到了BM算法。
#include<stack>
#include <iostream>


using namespace std;

char buf[] = "123456789";


/*
函数:int* MakeSkip(char *, int)
目的:根据坏字符规则做预处理,建立一张坏字符表
参数:
ptrn => 模式串P
PLen => 模式串P长度
返回:
int* - 坏字符表
*/
int* MakeSkip(char *ptrn, int pLen)

 int i;
 //为建立坏字符表,申请256个int的空间
 /*PS:之所以要申请256个,是因为一个字符是8位,
 所以字符可能有2的8次方即256种不同情况*/
 int *skip = (int*)malloc(256*sizeof(int));

 if(skip == NULL)
 {
  fprintf(stderr, "malloc failed!");
  return 0;
 } 

 //初始化坏字符表,256个单元全部初始化为pLen
 for(i = 0; i < 256; i++)
 {
  *(skip+i) = pLen;
 }

 //给表中需要赋值的单元赋值,不在模式串中出现的字符就不用再赋值了
 while(pLen != 0)
 {
  *(skip+(unsigned char)*ptrn++) = pLen--;
 }

 return skip;
}


/*
函数:int* MakeShift(char *, int)
目的:根据好后缀规则做预处理,建立一张好后缀表
参数:
ptrn => 模式串P
PLen => 模式串P长度
返回:
int* - 好后缀表
*/
int* MakeShift( char* ptrn,int pLen)
{
 //为好后缀表申请pLen个int的空间
 int *shift = (int*)malloc(pLen*sizeof(int));
 int *sptr = shift + pLen - 1;//方便给好后缀表进行赋值的指标
 char *pptr = ptrn + pLen - 1;//记录好后缀表边界位置的指标
 char c;

 if(shift == NULL)
 {
  fprintf(stderr,"malloc failed!");
  return 0;
 }

 c = *(ptrn + pLen - 1);//保存模式串中最后一个字符,因为要反复用到它

 *sptr = 1;//以最后一个字符为边界时,确定移动1的距离

 pptr--;//边界移动到倒数第二个字符(这句是我自己加上去的,因为我总觉得不加上去会有BUG

,大家试试“abcdd”的情况,即末尾两位重复的情况)

 while(sptr-- != shift)//该最外层循环完成给好后缀表中每一个单元进行赋值的工作
 {
  char *p1 = ptrn + pLen - 2, *p2,*p3;

  //该do...while循环完成以当前pptr所指的字符为边界时,要移动的距离
  do{
   while(p1 >= ptrn && *p1-- != c);//该空循环,寻找与最后一个字符c匹配

的字符所指向的位置

   p2 = ptrn + pLen - 2;
   p3 = p1;

   while(p3 >= ptrn && *p3-- == *p2-- && p2 >= pptr);//该空循环,判断在

边界内字符匹配到了什么位置

  }while(p3 >= ptrn && p2 >= pptr);

  *sptr = shift + pLen - sptr + p2 - p3;//保存好后缀表中,以pptr所在字符为边界

时,要移动的位置
  /*
  PS:在这里我要声明一句,*sptr = (shift + pLen - sptr) + p2 - p3;
  大家看被我用括号括起来的部分,如果只需要计算字符串移动的距离,那么括号中的那

部分是不需要的。
  因为在字符串自左向右做匹配的时候,指标是一直向左移的,这里*sptr保存的内容,

实际是指标要移动
  距离,而不是字符串移动的距离。我想SNORT是出于性能上的考虑,才这么做的。  

 
  */

  pptr--;//边界继续向前移动
 }

 return shift;
}


/*
函数:int* BMSearch(char *, int , char *, int, int *, int *)
目的:判断文本串T中是否包含模式串P
参数:
buf => 文本串T
blen => 文本串T长度
ptrn => 模式串P
PLen => 模式串P长度
skip => 坏字符表
shift => 好后缀表
返回:
int - 1表示成功(文本串包含模式串),0表示失败(文本串不包含模式串)。
*/
int BMSearch( char *ptrn,char *buf)
{
 cout<<"ptrn  "<<ptrn<<endl;
 cout<<"buf  "<<buf<<endl;
 cout<<"--------------------"<<endl;
 int plen = strlen(ptrn);
 
 int b_idx = plen; 
 int blen = strlen(buf);
 

 if (plen == 0)
  return 0;
 if (plen == 1)
 {
  if (strchr(buf,ptrn[0]))
  {
   return 1;
  }
  else return 0;
 }
 int *skip  = MakeSkip(ptrn,plen);
 int *shift = MakeShift(ptrn,plen);

 while (b_idx <= blen)//计算字符串是否匹配到了尽头
 {
  int p_idx = plen, skip_stride, shift_stride;
  while (buf[--b_idx] == ptrn[--p_idx])//开始匹配
  {
   if (b_idx < 0)
    return 0;
   if (p_idx == 0)
   {    
    return 1;
   }
  }
  skip_stride = skip[(unsigned char)buf[b_idx]];//根据坏字符规则计算跳跃的距离
  shift_stride = shift[p_idx];//根据好后缀规则计算跳跃的距离
  b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;//取大者
 }
 return 0;
}


/**
*0 not found
*-1 expression illegal 
*1 found
*/
int judePtrStr(string & target,char* buf)
{
 stack<string> opnd;//操作数
 stack<char>optr;//操作符
 stack<string>operate;//运算符
 bool restult = true;
 bool isUse = false;

 
 while (!target.empty())
 {
  //cout<<" 括号数 为"<<optr.size()<<endl;
  switch(target[0])
  {
  case ' ':
   {
    target.erase(0,1);
    break;
   }
  case '\"':
   {
    target.erase(0,1);
    size_t resultQuote = target.find('\"');
    if (string::npos != resultQuote )
    {
     string tempOpnd = target.substr(0,resultQuote);
     target.erase(0,resultQuote+1);
     
     opnd.push(tempOpnd);
     
     
    }
    else
    {
     return -1;
    }
    break;
   }
  case 'a':
   {
    string tempAnd = target.substr(0,3);
    
    if (tempAnd == "and")
    {
     target.erase(0,3);
     
     if (!opnd.empty())
     {
      string tempOpnd = opnd.top();
      opnd.pop();

      char   *p=new   char[tempOpnd.size()+1];
      strcpy(p,tempOpnd.c_str());
      
      if (!isUse)
      {
       restult = BMSearch(p,buf);
       isUse = true;
      }
      else
      {
       if (!operate.empty())
       {
        string tempOper =

operate.top();
        if (tempOper == "and")
        {
         restult =BMSearch

(p,buf)&&restult;
        }
        else restult =BMSearch

(p,buf)||restult;
       }
       
      }
      delete p;
     }
     
     operate.push("and");
     if (!restult)
     {
      //删除元素,直到遇到or或 (,且or不在引号中
      int quoteNum=0;
      int bracketNum = 0;
      while (!target.empty())
      {
       
       if (target[0] =='\"' )
       {
        ++quoteNum;
       }
       else if (target[0] == '(')
       {
        ++bracketNum;
        optr.push('(');
       }
       else if (target[0] == ')')
       {
         bracketNum--;
        if (!optr.empty())
        {
         optr.pop();
        }
        else return -1;//括号不匹配
        
       }
       else if (target[0] ==

'o'&&quoteNum%2 == 0&&bracketNum==0)
       {
        if (target[1] == 'r'&&

(target[2]=='\"'||target[2] == ' '))
        {
         break;
        }
       }
       target.erase(0,1);
      }
     }
     
    }
    else
     return -1;//不是and 肯定非法
    
    break;

   }
  case 'o':
   {
    string tempAnd = target.substr(0,2);
    if (tempAnd == "or")
    {
     target.erase(0,2);
     
     if (!opnd.empty())
     {
      

      string tempOpnd = opnd.top();
      opnd.pop();

      char   *p=new   char[tempOpnd.size()+1];
      strcpy(p,tempOpnd.c_str());

      if (!isUse)
      {
       restult = BMSearch(p,buf);
       isUse = true;
      }
      else
       if (!operate.empty())
       {
        string tempOper =

operate.top();
        if (tempOper == "and")
        {
         restult =BMSearch

(p,buf)&&restult;
        }
        else restult =BMSearch

(p,buf)||restult;
       }
      delete p;
     }
     
     operate.push("or");
     
     if (restult)
     {
      //删除元素,直到遇到),且)不在引号中
      int quoteNum=0;
      int bracketNum = 0;
      while (!target.empty())
      {

       if (target[0] =='\"' )
       {
        ++quoteNum;
       }
        else if (target[0] == '(')
        {
         bracketNum++;
        }
       else if (target[0] ==

')'&&quoteNum%2 == 0)
       {
        //target.erase(0,1);
        if (bracketNum == 0)
        {
         break;
        }
        else bracketNum--;
        

       }
       target.erase(0,1);
      }
     }
     
    }
    else
     return -1;//不是or 非法    

    break;

   }
  case '(':
   {
    optr.push('(');
    target.erase(0,1);
    break;
   }
  case ')':
   {
    target.erase(0,1);
    if (optr.empty())
    {
     return -1;
    }
    char c = optr.top();;    
    
    if ( c != '(')
    {
     return -1;//括号不匹配
    }
    else optr.pop();
    break;
   }
  default:
   return -1;//参数非法,未知类型
  }
  
 }
 
 if (!opnd.empty())
 {
  string tempOpnd = opnd.top();
  opnd.pop();
  
  char   *p=new   char[tempOpnd.size()+1];
  strcpy(p,tempOpnd.c_str());

  restult =BMSearch(p,buf);//此处不能直接返回有可能有括号不匹配的情况
  delete p;
  
 }
 if (!optr.empty())
 {
  return -1;//括号不匹配
 }
 return restult;

}


int main()
{/*
 string cc = "\"7\"and \"23\"and\"1\"or \"a\"";
 string cc = "\"7\"and \"a\"and\"1\"or \"a\"";
 string cc = "\"7\"or \"a\"and\"1\"or \"a\"";
 string cc = "(\"7\"or \"1\")and\"a\"";
 string cc = "\"7\"and \"1\"and\"a\"";
 string cc = "(\"7\"and \"1\")and\"a\"";
 string cc = "\"7\"and (\"1\"or\"a\")";
 string cc = "\"a\"and (\"1\"or\"a\")";
 string cc = "\"a\"or ((\"1\"or\"a\")and\"l\")";
 string cc = "\"a\"or ((\"1\"or\"a\")and\"4\")";
 string cc = "\"a\"or ((\"1\"or\"a\")and\"4\"";
 string cc = "\"a\"or ((\"1\"or\"a\")and\"4\"and\"l\"";
 string cc = "\"a\"or ((\"1\"or\"a\")and\"4\"and\"2\"and\"3\"and\"5\"and\"6\"and\"7

\"and\"0\"";
 string cc = "\"a\"or ((\"1\"or\"a\")and\"4\"and\"2\"and\"3\"and\"5\"and\"6\"and\"7

\"and\"8\"";
 string cc = "(((\"a\"or ((\"1\"or\"a\"))or\"2\")or\"3\")and(\"4\"and\"5\")";
 string cc = "(((\"a\"or ((\"1\"or\"a\"))or\"2\")or\"3\")and(\"4\"and\"5\"))";
 string cc = "(((\"a\"or ((\"1\"or\"a\"))or\"2\")or\"3\")and(\"4\"and\"0\")";
 string cc = "(((\"a\"or ((\"1\"or\"a\"))or\"2\")or\"3\")and(\"4\"and\"0\"))or\"p\"";
 string cc = "(((\"a\"or ((\"1\"or\"a\"))or\"2\")or\"3\")and((\"4\"and\"0\"))

or\"p\")";
 string cc = "(((\"a\"and ((\"1\"or\"c\"))or\"2\")or\"3\")and(\"4\"and\"0\"))

or\"p\"";
 string cc = ")))";
 string cc = "())";*/
 //string cc = "(((\"a\"and ((\"1\"or\"c\"))or\"2\")or\"3\")and(\"R\"and\"0\"))

or\"p\"";

 /*string buf1 = "Ncp Recveive Message From Smcc: CmdCode = 0x5006,lParamLen =

0x0.";*/

 string buf1 = "Ncp Send Message To Mcu:  nMcuAdrs=0x 10301 CmdCode =

0x11ab,lParamLen = 0x12.\n"
  "--------- NCP TO MCU ---------- The Content of Message Buffer is: \n"
 "01  03  01  01  12  01  ff  ff  ff  fe  ff  ff  ff  fe  11  ab  fe  01  fe  fe  00 

00  00  12  00  01 \n"
  "01  12  01  fe  fe  fe  00  01  00  01  02  02  fe  fe  fe  fe  fe  fe\n"
  "Set the(slot:3 port:1) device type:ETHERNET\n"
  "Comm process(0) send msg to Smcc(192.192.1.5) successfully! CmdCode:

0x5006\n";

char *p1 = new char[buf1.size()+1];
 strcpy(p1,buf1.c_str());
 
 /*string ptrn = "\"Ncp\" and \"Send\" or \"core\"";
 string ptrn = "\"Ncp\" and \"core\"";

 string ptrn = "(\"Ncp\" or \"core\")and \"Message\"and \"core\"";

 string ptrn = "(\"Ncp\" or \"core\")and \"Message\"or \"core\"";
 string ptrn = "((\"Ncp\" or \"core\")and \"Message\"or \"core\")and\"core\"";*/
 string ptrn = "((\"Ncp\" and \"core\")and \"Message\"or \"core\")and\"core\"";
 
  
  int resutl = judePtrStr(ptrn,p1);
  cout<<"============buf1 begin==============="<<endl;
  if (resutl == 1)
  {
   cout<<buf1<<endl;
  }
  cout<<"============buf1 end==============="<<endl;

system("pause");

 
}

原文地址:https://www.cnblogs.com/corecible/p/1761264.html