正则表达式部分特征实现设计实验
2015-10-24 23:35
387 查看
正则表达式
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("\r\n");
}
// 创建新的存储空间, 拷贝字符串的子串
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] = '\0';
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 = '\0';
if ( ptStrObj->iIndex >= ptStrObj->iLen )
{
// 已到尾部,无字符串可取
return '\0';
}
// 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 = '\0';
if ( ptStrObj->iIndex >= ptStrObj->iLen )
{
// 已到尾部,无字符串可取
return '\0';
}
// 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 == '\0' )
{
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 == '\0' )
{
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 == '\0' )
{
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 == '\0' )
{
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!\n", 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;
}
相关文章推荐
- ubuntu中安装chkconfig
- Sliding Window Maximum 解答
- [置顶] Git常用命令
- GRAPHITE SERIES #3: WHISPER STORAGE SCHEMAS & AGGREGATIONS
- block简单回顾
- 与地图相关的代码段
- dubbo初识(1)
- /sbin/insserv: No such file or directory
- 夺命雷公狗---无限级分类NO7
- Vi命令一览
- 约瑟夫环
- Android jni 编程2(对基本类型一维整型数组的操作)
- xamarin IOS C#
- javascript语法基础1
- lintcode-用递归打印数字
- 解决Hessian调用重载方法报错问题
- 安卓 基于监听接口的事件处理
- 神奇的pow()函数
- python爬虫的一些心得
- MongoDB服务端JavaScript脚本使用方法