zoukankan      html  css  js  c++  java
  • 正则表达式部分特征实现设计实验

    正则表达式

    http://www.regexlab.com/zh/regref.htm

      正则表达式(regular expression)就是用一个“字符串”来描述一个特征,然后去验证另一个“字符串”是否符合这个特征。比如 表达式“ab+” 描述的特征是“一个 'a' 和 任意个 'b' ”,那么 'ab', 'abb', 'abbbbbbbbbb' 都符合这个特征。

        正则表达式可以用来:(1)验证字符串是否符合指定特征,比如验证是否是合法的邮件地址。(2)用来查找字符串,从一个长的文本中查找符合指定特征的字符串,比查找固定字符串更加灵活方便。(3)用来替换,比普通的替换更强大。

    正则表达式一般有如下基本规则, 本文尝试编码实现:

    1.       * 表示任意个
    
    2.       +表示至少一个
    
    3.       ?表示0到一个
    
    4.       {n}表示精确匹配n个
    
    5.       []表示字符集合,匹配所包含的任意一个字符
    
    6.       x|y表示匹配 x 或 y

    --------

    实现思路分析

    ---- 分析 ----

    1、 首先正则表达式匹配, 是使用 正则字符串 匹配 普通字符串

          第一件要做的是,普通字符串解析,所以普通字符串解析功能需要实现。

    2、 其次, 正则字符串也需要解析, 需要实现 正则字符串(表达式) 解析功能。

    3、 解析正则字符串过程, 及时进行 与普通字符串的匹配工作。

      每当解析出一个正则字符,则执行此正则字符, 与普通字符的匹配。

    ---- 待实现的正则表达元素 ------

    分为三类:

    (1) 修饰符, 用于修饰字符出现的次数:

    1.       * 表示任意个
    
    2.       +表示至少一个
    
    3.       ?表示0到一个
    
    4.       {n}表示精确匹配n个

    (2) 可匹配多种字符的正则字符写法

    5.       []表示字符集合,匹配所包含的任意一个字符

    (3) 可匹配多种字符的正则字符写法

    6.       x|y表示匹配 x 或 y

    --- 实现步骤 ---

    1、 实现第 1 点 字符串解析,将字符串作为对象定义, 实现其应有的方法。

    2、 先不考虑正则字符串的解析, 将正则字符串作为普通字符串看待,

      实现正则字符串解析 与 普通字符串的匹配工作。

      此步骤实现了, 程序的基本流程。

    3、 将正则字符串的解析添加到第二步的流程中,

          (1)  * + ?表示对 字符出现数目的修饰, 属于修饰符, 在解析正则表达式, 只需要读取一个字符匹配,

      ,  且匹配普通字符串, 可以统一到{开始次数,结束次数}中。 对于三个字符, 实现逻辑大体相同, 可以第一步实现。

      (2) {n} 在正则字符后匹配一个三个符,需要在兼容* + ?解析后,

      支持多个字符读取, 并匹配{n},解析出n值。 在(1)上做结构性修改即可, 所以安排第二步实现。

      (3) [] 是对正则字符的主体进行的扩展, 即其支持的匹配字符可以是多个, 

      此步骤实现后, 对正则字符是个扩充, (1)(2)步骤, 只需要char, 此步骤需要string。

      (4) | 可匹配多种字符的正则字符写法, 同(3), 解析过程将 可选择的字符 存储到 (3)中实现的string数据结构中。

    ------- 实现模式 ----------

    1、 修饰符的提取:   每种修饰符的 提取方法, 和  修饰符对普通字符串的匹配方法, 各不相同,

      但是 正则字符的提取 然后 执行匹配的 流程是 固定的, 将此过程写成固定的方法,

      将修饰符的 两种函数 做成一个表, 流程中一次调用 提取函数, 提取成功, 则执行响应修饰符的 普通匹配函数。

    /* ------------------------------ 全局变量 --------------------------------- */
    T_PATCHAR_MODIFIER g_patCharModifier[] = {
        {MODIFIER_TYPE_FIXCOUNT, MatchFixCount, DoMatchStrByFixCount},
        {MODIFIER_TYPE_QUESTIONMARK, MatchQuestionMark, DoMatchStrByQuestionMark},
        {MODIFIER_TYPE_ZEROPLUS, MatchZeroPlus, DoMatchStrByZeroPlus},
        {MODIFIER_TYPE_ONEPLUS, MatchOnePlus, DoMatchStrByOnePlus},
        
        // plain 必须放在最后, 以满足, 其他修饰符都未匹配,默认使用此匹配符号
        {MODIFIER_TYPE_NOMODIFIER,    MatchNoModifier,    DoMatchStrByNoModifier},
    };

    2、 正则字符提取, []  和 | 都是要 提取 可匹配的字符 集合, 也采用修饰符的实现模式,

      将 []  和 | 的解析函数, 和 普通字符解析函数 做成一个表,

      对于每次字符匹配, 匹配成功, 则确定了 可匹配字符集。

    GetOptCharsFunc g_getOptCharsFunc[] = {
        GetOptCharsByOrExpress, // 0|1
        GetOptCharsBySetExpress,  // [01]
    
        // no express must be set to tail, as default valid action
        GetOptCharsByNoExpress,  // 0
    };

    C 代码实现

    https://github.com/fanqingsong/code-snippet/blob/master/C/regularExpress/cRegFunc.cpp

    
    #include <stdio.h>
    #include <string.h>
    #include <assert.h>
    #include <malloc.h>
    #include <stdarg.h>
    
    
    /* ------------------------------ 声明区域 --------------------------------- */
    
    // list node
    typedef struct node{
        char* str;
        struct node* next;
    } T_NODE, *PT_NODE;
    
    typedef enum returnType {
        FAIL = 0,
        SUCCESS,
    } E_RETURN_TYPE;
        
    typedef enum boolType {
        FALSE = 0,
        TRUE,
    } E_BOOL_TYPE;
    
    // pattern modifier : {} * +
    typedef enum ModifierType{
        MODIFIER_TYPE_NOMODIFIER, // PLAIN CHAR
        MODIFIER_TYPE_FIXCOUNT, // {X}
        MODIFIER_TYPE_ZEROPLUS, // *
        MODIFIER_TYPE_ONEPLUS, // +
        MODIFIER_TYPE_QUESTIONMARK, // ?
    } E_MODIFIER_TYPE;
    
    typedef struct patternChar{
        char szOptChars[128]; // option char , for muliti char from 0|2 and [23] express
        int iOptCharsLen;
        E_MODIFIER_TYPE modifyType; // modifier type : * + ?
        int modifyPara;
    } T_PAT_CHAR, *PT_PAT_CHAR;
    
    typedef struct stringObj{
        char* szStr;
        int iLen;
        int iIndex;
    } T_STRING_OBJ, *PT_STRING_OBJ;
    
    typedef E_BOOL_TYPE (*MatchModifier)(PT_STRING_OBJ, PT_PAT_CHAR);
    typedef E_BOOL_TYPE (*MatchStrByModifier)(PT_PAT_CHAR, PT_STRING_OBJ);
    
    typedef struct PatCharModifier{
        E_MODIFIER_TYPE modifyType;
        MatchModifier matchModifier;
        MatchStrByModifier matchStrByModifier;
    } T_PATCHAR_MODIFIER, PT_PATCHAR_MODIFIER;
    
    typedef E_BOOL_TYPE (*GetOptCharsFunc)(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptPatObj);
    
    void MyPrintf(char* fmt, ...);
    char* DupSubStr(char* str, int start, int end);
    void StopWithMsg(char* msg);
    
    /* 修饰符获取 和 依照修饰符匹配函数簇 */
    E_BOOL_TYPE MatchFixCount(PT_STRING_OBJ ptPatObj, PT_PAT_CHAR ptPatChar);
    E_BOOL_TYPE DoMatchStrByFixCount(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj);
    
    E_BOOL_TYPE MatchQuestionMark(PT_STRING_OBJ ptPatObj, PT_PAT_CHAR ptPatChar);
    E_BOOL_TYPE DoMatchStrByQuestionMark(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj);
    
    E_BOOL_TYPE MatchZeroPlus(PT_STRING_OBJ ptPatObj, PT_PAT_CHAR ptPatChar);
    E_BOOL_TYPE DoMatchStrByZeroPlus(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj);
    
    E_BOOL_TYPE MatchOnePlus(PT_STRING_OBJ ptPatObj, PT_PAT_CHAR ptPatChar);
    E_BOOL_TYPE DoMatchStrByOnePlus(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj);
    
    E_BOOL_TYPE MatchNoModifier(PT_STRING_OBJ ptPatObj, PT_PAT_CHAR ptPatChar);
    E_BOOL_TYPE DoMatchStrByNoModifier(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj);
    
    
    // 解析组合模式字符 表达形式   0|1  [01] 
    E_BOOL_TYPE GetOptCharsByOrExpress(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptPatObj);
    E_BOOL_TYPE GetOptCharsBySetExpress(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptPatObj);
    E_BOOL_TYPE GetOptCharsByNoExpress(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptPatObj);
    
    
    /* ------------------------------ 全局变量 --------------------------------- */
    T_PATCHAR_MODIFIER g_patCharModifier[] = {
        {MODIFIER_TYPE_FIXCOUNT, MatchFixCount, DoMatchStrByFixCount},
        {MODIFIER_TYPE_QUESTIONMARK, MatchQuestionMark, DoMatchStrByQuestionMark},
        {MODIFIER_TYPE_ZEROPLUS, MatchZeroPlus, DoMatchStrByZeroPlus},
        {MODIFIER_TYPE_ONEPLUS, MatchOnePlus, DoMatchStrByOnePlus},
        
        // plain 必须放在最后, 以满足, 其他修饰符都未匹配,默认使用此匹配符号
        {MODIFIER_TYPE_NOMODIFIER,    MatchNoModifier,    DoMatchStrByNoModifier},
    };
    
    GetOptCharsFunc g_getOptCharsFunc[] = {
        GetOptCharsByOrExpress, // 0|1
        GetOptCharsBySetExpress,  // [01]
    
        // no express must be set to tail, as default valid action
        GetOptCharsByNoExpress,  // 0
    };
    
    
    /* ------------------------------ 公共函数 --------------------------------- */
    // MyPrintf == puts + format args
    void MyPrintf(char* fmt, ...)
    {
        va_list args;
        va_start(args, fmt);
        vprintf(fmt, args);
        va_end(args);
       
        printf("
    ");
    }
    
    // 创建新的存储空间, 拷贝字符串的子串
    char* DupSubStr(char* str, int start, int end)
    {
        char* newStr = NULL;
       
        // sub string len 开区间 计算子串长度
        int len = end - start + 1;
       
        // regarding ending zero
        len++;
       
        newStr = (char*)malloc( sizeof(char)*len );
       
        if ( NULL == newStr )
        {
            return NULL;
        }
       
        newStr[len-1] = '';
        strncpy(newStr, str+start, len-1);
       
        return newStr;
    }
    
    void StopWithMsg(char* msg)
    {
        puts(msg);
        assert(0);
    }
    
    /* ------------------------------ 链表函数 --------------------------------- */
    void FreeList(PT_NODE ptHeadNode)
    {
        PT_NODE ptCurNode = ptHeadNode->next;
        PT_NODE ptNextNode = NULL;
        while(ptCurNode)
        {
            ptNextNode = ptCurNode->next;
            if ( ptCurNode->str != NULL )
            {
                free(ptCurNode->str);
            }
            free(ptCurNode);
            ptCurNode = ptNextNode;
        }
    }
    
    int Insert2List(PT_NODE ptHeadNode, char* str)
    {
        PT_NODE ptNode = NULL;
        PT_NODE ptFirst = NULL;
       
        //MyPrintf("Insert2List str is %s", str);
       
        ptNode = (PT_NODE) malloc(sizeof(T_NODE));
        if ( ptNode == NULL )
        {
            return -1;
        }
       
        ptNode->str = str;
       
        ptFirst = ptHeadNode->next;
        ptHeadNode->next = ptNode;
        ptNode->next = ptFirst;
    }
    
    void PrintList(PT_NODE ptHeadNode)
    {
        PT_NODE ptCurNode = NULL;
        MyPrintf("---- list printing begin -----");
     
         ptCurNode = ptHeadNode->next;
        while(ptCurNode)
        {
            MyPrintf("node str is %s", ptCurNode->str);
            ptCurNode = ptCurNode->next;
        }
       
        MyPrintf("---- list printing end -----");
    }
    
    void AssertList(PT_NODE ptHeadNode, char* strArr[]){
        int index = 0;
        PT_NODE ptCurNode = ptHeadNode->next;
       
        while(ptCurNode)
        {
            if ( strArr[index] == NULL )
            {
                StopWithMsg("strArr reach top, but list not over.");
                return;
            }
           
            if ( strcmp(ptCurNode->str, strArr[index]) == 0 )
            {
                //MyPrintf("List index[%d] str [%s] matched.", index, strArr[index]);
                index++;
                ptCurNode = ptCurNode->next;
            }
            else
            {
                StopWithMsg("List index str don't matched.");
                return;
            }
        }
       
        if ( strArr[index] != NULL )
        {
            StopWithMsg("AssertList failed.");
            return;
        }
        else
        {
            //MyPrintf("match all");
        }
    }
    
    void TestList()
    {
        T_NODE headNode = {NULL, NULL};
       
        Insert2List(&headNode, "first");
        Insert2List(&headNode, "second");
       
        PrintList(&headNode);
       
        char* strArr[] = {
            "second",
            "first",
            NULL
        };
        AssertList(&headNode, strArr);
        FreeList(&headNode);
    }
    
    // list 链表操作测试用例
    void TestListCase()
    {
        TestList();
    }
    
    /* ------------------------------ 普通字符串 -------------------------------- */
    // 初始化字符串对象
    void InitStrObjStruct(PT_STRING_OBJ ptStrObj)
    {
        ptStrObj->iLen = strlen(ptStrObj->szStr);
        ptStrObj->iIndex = 0;
    }
    
    // 从字符串中获取当前一个字符,并将指针指向下一个字符
    char GetCharFromStr(PT_STRING_OBJ ptStrObj)
    {
        char retChar = '';
        
        if ( ptStrObj->iIndex >= ptStrObj->iLen )
        {
            // 已到尾部,无字符串可取
            return '';
        }
        
        // get current char
        retChar = ptStrObj->szStr[ptStrObj->iIndex];
        
        // navigate to next char
        ptStrObj->iIndex++;
        
        return retChar;
    }
    
    // 从字符串中获取当前一个字符,不执行指针指向下一个字符
    char GetCharFromStr_purely(PT_STRING_OBJ ptStrObj)
    {
        char retChar = '';
        
        if ( ptStrObj->iIndex >= ptStrObj->iLen )
        {
            // 已到尾部,无字符串可取
            return '';
        }
        
        // get current char
        retChar = ptStrObj->szStr[ptStrObj->iIndex];
        
        return retChar;
    }
    
    //比较字符, 迁移str的index
    E_BOOL_TYPE MatchCharInStr(char cChar, PT_STRING_OBJ ptStrObj)
    {
        char cCurChar = GetCharFromStr(ptStrObj);
        if ( cCurChar == '' )
        {
            return FALSE;
        }
        
        if ( cChar == cCurChar )
        {
            return TRUE;
        }
        
        return FALSE;
    }
    
    //只比较字符, 不迁移str的index
    E_BOOL_TYPE MatchCharInStr_purely(char cChar, PT_STRING_OBJ ptStrObj)
    {
        char cCurChar = GetCharFromStr_purely(ptStrObj);
        if ( cCurChar == '' )
        {
            return FALSE;
        }
        
        if ( cChar == cCurChar )
        {
            return TRUE;
        }
        
        return FALSE;
    }
    
    //比较Optional字符, 比较成功迁移str的index
    E_BOOL_TYPE MatchOptCharsInStr(char* szOptChars, PT_STRING_OBJ ptStrObj)
    {
        char cCurChar = GetCharFromStr_purely(ptStrObj);
        if ( cCurChar == '' )
        {
            return FALSE;
        }
    
        // 字符串中含有字符
        if ( strchr(szOptChars, cCurChar) )
        {
            ptStrObj->iIndex++;
            return TRUE;
        }
        
        return FALSE;
    }
    
    /* ------------------------------ 模式匹配 --------------------------------- */
    // from pattern begining, match {xx}, xx is digits [1234567890]
    int MatchCurlyBracket(char* str, int* piFixCount)
    {
        int span = 0;
        
        if ( !str )
        {
            return 0;
        }
        
        if ( str[0] != '{' )
        {
            return 0;
        }
        
        // count { len
        span++;
        
        int count = strspn(str+span, "1234567890");
        //MyPrintf("MatchCurlyBracket count=%d", count);
        if ( count == 0 )
        {
            return 0;
        }
        
        //count xx length, xx in {xx}
        span += count;
        
        if ( str[span] != '}' )
        {
            return 0;
        }
        
        // count } len
        span++;
        
        char* sTemp = DupSubStr(str+1, 0, count-1);
        if ( sTemp == NULL )
        {
            return 0;
        }
        
        *piFixCount = atoi(sTemp);
        free(sTemp);
        sTemp = NULL;
        
        return span;
    }
    
    // if match fixcount modifier, then renew patObj, and record to patChar
    E_BOOL_TYPE MatchFixCount(PT_STRING_OBJ ptPatObj, PT_PAT_CHAR ptPatChar)
    {
        int fixCount = 0;
        int span = 0;
        
        span = MatchCurlyBracket(ptPatObj->szStr+ptPatObj->iIndex, &fixCount);
        
        //MyPrintf("GetPatCharFromPattern MatchCurlyBracket=%d", span);
        if ( span > 0 )
        {
            ptPatObj->iIndex += span;
            
            ptPatChar->modifyType = MODIFIER_TYPE_FIXCOUNT;
            ptPatChar->modifyPara = fixCount;
            
            return TRUE;
        }
        
        return FALSE;
    }
    
    E_BOOL_TYPE DoMatchStrByFixCount(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj)
    {
        int fixCount = ptPatChar->modifyPara;
        char* szOptChars = ptPatChar->szOptChars;
        
        int index = 0;
        for ( index=0; index<fixCount; index++ )
        {
            if ( !MatchOptCharsInStr(szOptChars, ptStrObj) )
            {
                return FALSE;
            }
        }
        
        return TRUE;
    }
    
    E_BOOL_TYPE MatchQuestionMark(PT_STRING_OBJ ptPatObj, PT_PAT_CHAR ptPatChar)
    {
        if ( '?' == ptPatObj->szStr[ptPatObj->iIndex] )
        {
            ptPatObj->iIndex++;
            
            ptPatChar->modifyType = MODIFIER_TYPE_QUESTIONMARK;
            
            return TRUE;
        }
        
        return FALSE;
    }
    
    E_BOOL_TYPE DoMatchStrByQuestionMark(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj)
    {
        char* szOptChars = ptPatChar->szOptChars;
        
        // 1? 先按照 1 来匹配
        int span = strspn(ptStrObj->szStr+ptStrObj->iIndex, szOptChars);
        if ( span >= 1 )
        {
            // 迁移一位
            ptStrObj->iIndex++;
            return TRUE;
        }
        
        // 1? 先按照 空 来匹配, 不迁移index
        return TRUE;
    }
    
    E_BOOL_TYPE MatchZeroPlus(PT_STRING_OBJ ptPatObj, PT_PAT_CHAR ptPatChar)
    {
        if ( '*' == ptPatObj->szStr[ptPatObj->iIndex] )
        {
            ptPatObj->iIndex++;
            
            ptPatChar->modifyType = MODIFIER_TYPE_ZEROPLUS;
            
            return TRUE;
        }
        
        return FALSE;
    }
    
    E_BOOL_TYPE DoMatchStrByZeroPlus(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj)
    {
        char* szOptChars = ptPatChar->szOptChars;
    
        // 贪婪匹配
        int span = strspn(ptStrObj->szStr+ptStrObj->iIndex, szOptChars);
        if ( span >= 1 )
        {
            // index迁移到不是 cChar 的字符
            ptStrObj->iIndex += span;
            return TRUE;
        }
        
        // zeroplus(*) 允许空匹配, 不迁移index
        return TRUE;
    }
    
    E_BOOL_TYPE MatchOnePlus(PT_STRING_OBJ ptPatObj, PT_PAT_CHAR ptPatChar)
    {
        if ( '+' == ptPatObj->szStr[ptPatObj->iIndex] )
        {
            ptPatObj->iIndex++;
            
            ptPatChar->modifyType = MODIFIER_TYPE_ONEPLUS;
            
            return TRUE;
        }
        
        return FALSE;
    }
    
    E_BOOL_TYPE DoMatchStrByOnePlus(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj)
    {
        char* szOptChars = ptPatChar->szOptChars;
        
        // 贪婪匹配
        int span = strspn(ptStrObj->szStr+ptStrObj->iIndex, szOptChars);
        if ( span >= 1 )
        {
            // index迁移到不是 cChar 的字符
            ptStrObj->iIndex += span;
            return TRUE;
        }
        
        // oneplus(+) 不允许空匹配
        return FALSE;
    }
    
    E_BOOL_TYPE MatchNoModifier(PT_STRING_OBJ ptPatObj, PT_PAT_CHAR ptPatChar)
    {
        ptPatChar->modifyType = MODIFIER_TYPE_NOMODIFIER;
        
        //作为普通字符,默认匹配通过
        return TRUE;
    }
    
    E_BOOL_TYPE DoMatchStrByNoModifier(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj)
    {
        char* szOptChars = ptPatChar->szOptChars;
    
        if ( !MatchOptCharsInStr(szOptChars, ptStrObj) )
        {
            return FALSE;
        }
        
        return TRUE;
    }
    
    // 0|1
    E_BOOL_TYPE GetOptCharsByOrExpress(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptPatObj)
    {
        char cChar = 0;
    
        // second char is not |, or express not santisfied
        if ( '|' != ptPatObj->szStr[ptPatObj->iIndex+1] )
        {
            return FALSE;
        }
    
        // prevent 0| pattern string ocurring, assuring x|y structure complete
        if ( '|'  == ptPatObj->szStr[ptPatObj->iLen-1] )
        {
            return FALSE;
        }
    
        cChar = GetCharFromStr(ptPatObj);
        ptPatChar->szOptChars[0] = cChar;
        ptPatChar->iOptCharsLen = 1;
    
        while ( (cChar = GetCharFromStr_purely(ptPatObj)) == '|' )
        {
            // skip |
            cChar = GetCharFromStr(ptPatObj);
    
            // store x from |x
            cChar = GetCharFromStr(ptPatObj);
            ptPatChar->szOptChars[ptPatChar->iOptCharsLen] = cChar;
            ptPatChar->iOptCharsLen++;
        }
    
        return TRUE;
    }
    
    // [01]
    E_BOOL_TYPE GetOptCharsBySetExpress(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptPatObj)
    {
        char cChar = 0;
        int count = 0;
        int span = 0;
    
        cChar = GetCharFromStr_purely(ptPatObj);
        // first letter is not the starting square bracket
        if ( '[' != cChar )
        {
            return FALSE;
        }
    
        // count [ length
        count++;
    
        span = strspn(ptPatObj->szStr+ptPatObj->iIndex+1, "1234567890");
        //[xx], xx length must be larger than 0
        if ( span == 0 )
        {
            return FALSE;
        }
    
        // count span length
        count += span;
    
        // ending square bracket is not satisfied
        if ( ptPatObj->szStr[count] != ']' )
        {
            return FALSE;
        }
    
        //count ] length
        count++;
    
        // copy xx to patChar, xx is in [xx]
        strncpy(ptPatChar->szOptChars, ptPatObj->szStr+ptPatObj->iIndex+1, span);
        ptPatChar->iOptCharsLen = span;
    
        // index nagivate
        ptPatObj->iIndex += count;
    
        return TRUE;
    }
    
    // 0
    E_BOOL_TYPE GetOptCharsByNoExpress(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptPatObj)
    {
        ptPatChar->szOptChars[0] = GetCharFromStr(ptPatObj);
        ptPatChar->iOptCharsLen =1;
    
        // default action, must be OK
        return TRUE;
    }
    
    // 从模式字符串中获取下一个模式字符
    E_RETURN_TYPE GetPatCharFromPattern(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptPatObj)
    {
        int index = 0;
        int len = 0;
        E_BOOL_TYPE bMatched = FALSE;
        
    
        char cChar = ptPatObj->szStr[ptPatObj->iIndex];
        // pattern char exhausted, get fail
        if ( cChar == '' )
        {
            return FAIL;
        }
        
        // get pattern char's  optional chars, for combination express, aka 0|1
        len = sizeof(g_getOptCharsFunc)/sizeof(GetOptCharsFunc);
        bMatched = FALSE;
        for ( index=0; index<len; index++ )
        {
            bMatched = g_getOptCharsFunc[index](ptPatChar, ptPatObj);
            if ( bMatched == TRUE )
            {
                break;
            }
        }
        MyPrintf("GetPatCharFromPattern ptPatChar->szOptChars=%s",  ptPatChar->szOptChars);
        
        //获取模式字符的 修饰符 例如 {xx}
        len = sizeof(g_patCharModifier)/sizeof(T_PATCHAR_MODIFIER);
        bMatched = FALSE;
        for ( index=0; index<len; index++ )
        {
            bMatched = g_patCharModifier[index].matchModifier(ptPatObj, ptPatChar);
            if ( bMatched == TRUE )
            {
                break;
            }
        }
        
        return SUCCESS;
    }
    
    // 从字符串开始位置 ,匹配模式字符 pattern char
    E_BOOL_TYPE MatchPatChar(PT_PAT_CHAR ptPatChar, PT_STRING_OBJ ptStrObj)
    {
        if( !ptPatChar || !ptStrObj )
        {
            return FALSE;
        }
        
        int len = sizeof(g_patCharModifier)/sizeof(T_PATCHAR_MODIFIER);
        int index = 0;
        E_BOOL_TYPE bMatched = FALSE;
        E_MODIFIER_TYPE eModType = MODIFIER_TYPE_NOMODIFIER;
        
        for ( index=0; index<len; index++ )
        {
            eModType = g_patCharModifier[index].modifyType;
    
            // 按照修饰符类型,对模式字符做匹配动作
            if ( eModType == ptPatChar->modifyType )
            {
                bMatched = g_patCharModifier[index].matchStrByModifier(ptPatChar, ptStrObj);
                break;
            }
        }
        
        return bMatched;
    }
     
    void GetMatchedList(PT_NODE ptHeadNode, char* pattern, char* str)
    { 
        T_STRING_OBJ tPatObj;
        T_STRING_OBJ tStrObj;
        T_PAT_CHAR tPatChar;
        
        if ( !pattern || !str )
        {
            StopWithMsg("GetMatedList argument null");
        }
        
        memset(&tPatObj, 0, sizeof(T_STRING_OBJ));
        memset(&tStrObj, 0, sizeof(T_STRING_OBJ));
        memset(&tPatChar, 0, sizeof(T_PAT_CHAR));
        
        tPatObj.szStr = pattern;
        tStrObj.szStr = str;
        
        InitStrObjStruct(&tPatObj);
        InitStrObjStruct(&tStrObj);
        
        E_BOOL_TYPE bAllPatCharMatched = TRUE;
        
        MyPrintf("pattern =%s", tPatObj.szStr);
        while( GetPatCharFromPattern(&tPatChar, &tPatObj) )
        {
            if ( !MatchPatChar(&tPatChar, &tStrObj) )
            {
                MyPrintf("pattern szOptChars=%s match fail", tPatChar.szOptChars);
                bAllPatCharMatched = FALSE;
                break;
            }
            
            MyPrintf("pattern szOptChars=%s match success", tPatChar.szOptChars);
        }
        
        char* szMatchStr = NULL;
        if ( bAllPatCharMatched )
        {
            szMatchStr = DupSubStr(tStrObj.szStr, 0, tStrObj.iIndex-1);
            Insert2List(ptHeadNode, szMatchStr);
        }
        
        // stub code
        //Insert2List(ptHeadNode, "35");
    }
    
    void TestPattern(char* pattern, char* str, char* strArr[])
    {
        T_NODE tHeadNode = {
            NULL,
            NULL
        };
       
        MyPrintf("<<-- pattern[%s] apply to str[%s] want [%s] BEGIN!", pattern, str, strArr[0]);
       
        GetMatchedList(&tHeadNode, pattern, str);
       
        //PrintList(&tHeadNode);
       
        AssertList(&tHeadNode, strArr);
       
        MyPrintf("-->> pattern[%s] apply to str[%s] want [%s] OK!
    ", pattern, str, strArr[0]);
       
        FreeList(&tHeadNode);
    }
    
    /* 测试用例:
    Pattern     string          result
    "35"        "354"           "35"
    "3{2}5"     "3354"          "335"
    "3{4}"      "3334"          null
    "1*"        "11123"         "","1","11","111" -- 按照贪婪策略匹配 
    "1?"        "11123"         "","1"   --- 两个结果理解上拆分为二个测试用例 ,见下面  test ? question mark
    "1|2|3"     "123"           "1"
    "[12]+"     "1123"          "1", "11", "112"
    */
    void TestPatternCase()
    {
        // test plain - no modifier
        char* strArr[] = {"35", NULL};
        TestPattern("35", "354", strArr);
       
        // test {} sign positive case
        char* strArr1[] = {"335", NULL};
        TestPattern("3{2}5", "3354", strArr1);
        
        // test {} sign negative case
        char* strArr2[] = {NULL};
        TestPattern("3{4}", "3334", strArr2);
        
        // test ? question mark - match one
        char* strArr3[] = {"1", NULL};
        TestPattern("1?", "11123", strArr3);
    
        // test ? question mark - match none    
        char* strArr4[] = {"", NULL};
        TestPattern("1?", "21123", strArr4);
        
        // test asterisk 
        //"1*"        "11123"         "","1","11","111" -- 贪婪匹配一个最长值 
        char* strArr5[] = {"111", NULL};
        TestPattern("1*", "11123", strArr5);
        
        char* strArr51[] = {"", NULL};
        TestPattern("1*", "21123", strArr51);
        
        // test asterisk 
        //"1+"        "11123"         "1","11","111"  -- 贪婪匹配一个最长值 
        char* strArr6[] = {"111", NULL};
        TestPattern("1+", "11123", strArr6);
        
        char* strArr61[] = {NULL};
        TestPattern("1+", "21123", strArr61);
        
        // test or express
        //"1|2|3"     "123"           "1"
        char* strArr7[] = {"1", NULL};
        TestPattern("1|2|3", "123", strArr7);
        
        // test set express
        //"[12]+"     "1123"          "1", "11", "112"
        char* strArr8[] = {"112", NULL};
        TestPattern("[12]+", "1123", strArr8);
    }
    
    int main(void)
    {
        // test list function
        //TestListCase();
       
        // test pattern case
        TestPatternCase();
       
        return 0;
    }
    
    
  • 相关阅读:
    ExtJS Form布局
    UML系列 (六)如何提取用例技术?
    牛腩新闻发布系统 (4)验证码的生成
    DIV +CSS 系列详细教程 (一)初识
    Java、JavaScript、asp.net 、jquery 详细分析
    设计模式详细系列教程 (三)以网上购物通用的订单流程 详解状态模式
    设计模式详细系列教程 (四) 无处不在的单例模式
    SCM软件配置管理 (二) SVN管理平台搭建以及详细设置
    JAVA JDK环境变量的配置
    牛腩新闻发布系统 (5) 总结
  • 原文地址:https://www.cnblogs.com/lightsong/p/4908032.html
Copyright © 2011-2022 走看看