c实现极简单的正则表达式解析
define 头文件
///define 头文件///
#ifndef _DEFINE_H_
#define _DEFINE_H_
#define REGEX_LENGTH 40
//typedef unsigned char uint8;
typedef enum
{
IS_LETTER_OR_NUMBER = 0x11, //字母或数字
IS_NUMBER = 0x22, //数字
IS_RANGE = 0x33, //范围
IS_SPECIAL_VALUE = 0x44, //指定值
IS_ERROR_TYPE = 0XAA, //错误类型
}valueType;
typedef struct _STRUCT_VALUE_TYPE_INFOR
{
valueType uType;
uint8 uRange[2];
}STRUCT_VALUE_TYPE_INFOR;
#endif
regex_analysis头文件
///regex_analysis头文件///
#ifndef _REGEX_ANALYSIS_H_
#define _REGEX_ANALYSIS_H_
#include "define.h"
enum COMPILE_ERROR
{
REGEX_SUCCESS = 0,
REGEX_ERROR,
REGEX_LENGTH_ERROR
};
uint8 compile_regex(uint8 * regex);
bool match_regex(const uint8 * data, uint8 uSum);
#endif
regex_analysis源文件
///regex_analysis源文件///
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include "regex_analysis.h"
/*
说明:
这里的正则表达式解析是非常精简的处理,主要规则如下:
1.\w 表示字母(大、小)或数字
2.\d 表示数字
3.{n} 表示重复n次,n大于或等于1
4.[A-Z],[1-9],[a-z]分别表示具体范围
5.LN(B-2)E+D 直接列出字母、数字或包含在[0x20-0x7e]范围内ascii码值的表示列出内容本身
6.{n}{m}的写法是不被允许的
7.目前只支持如上列出的“元字符”
8.具体详细的规则可参照网上正则表达式的说明
*/
static STRUCT_VALUE_TYPE_INFOR g_stValueTypeInfor[REGEX_LENGTH];
void init_value_type_infor(void)
{
uint8 i = 0;
for(; i < REGEX_LENGTH; i++)
{
g_stValueTypeInfor[i].uType = IS_ERROR_TYPE;
g_stValueTypeInfor[i].uRange[0] = 0;
g_stValueTypeInfor[i].uRange[1] = 0;
}
}
//这里会把“编译”后的值信息放到g_stValueTypeInfor数组中
uint8 compile_regex(uint8 * regex)
{
uint8 *pRegex = regex;
uint8 uVINCount = 0;
uint8 uOffset = 0;
uint8 uOffsetSum = 0;
if(pRegex == NULL)
return REGEX_ERROR;
init_value_type_infor();
while(*pRegex != '\0')
{
switch(*pRegex)
{
case '\\':
{
if((pRegex[1] != 'w') && (pRegex[1] != 'd'))
return REGEX_ERROR;
if (pRegex[1] == 'w')
{
g_stValueTypeInfor[uVINCount].uType = IS_LETTER_OR_NUMBER;
}
else if (pRegex[1] == 'd')
{
g_stValueTypeInfor[uVINCount].uType = IS_NUMBER;
}
uVINCount += 1;
uOffset = 2;
}
break;
case '{':
{
uint8 n = 0;
uint8 i = 0;
if((!isdigit(pRegex[1])) || (pRegex[2] != '}'))//若{n}中不是数字则认为是错误的
return REGEX_ERROR;
if(uOffsetSum == 0)//{n}写在表达式的开头是错误的
return REGEX_ERROR;
if(regex[uOffsetSum - 1] == '}')//{n}{m}这样写是错误的
return REGEX_ERROR;
n = pRegex[1] - 0x30;
if(n == 0)
return REGEX_ERROR;
for (; i < n - 1; i++)
{
g_stValueTypeInfor[uVINCount - 1 + i + 1] = g_stValueTypeInfor[uVINCount - 1];//复制前一个
}
uVINCount += n - 1;
uOffset = 3;
}
break;
case '[':
{
if( !isalnum(pRegex[1]) ||(pRegex[2] != '-')
|| !isalnum(pRegex[3]) ||(pRegex[4] != ']'))//[A-Z] OR [0-9] or [a-z] 并不严格判断 [0-z] is ok
return REGEX_ERROR;
g_stValueTypeInfor[uVINCount].uType = IS_RANGE;
g_stValueTypeInfor[uVINCount].uRange[0] = pRegex[1];
g_stValueTypeInfor[uVINCount].uRange[1] = pRegex[3];
uVINCount += 1;
uOffset = 5;
}
break;
default:
{
if( !isprint(pRegex[0]) )//可打印字符[0x20-0x7e]
return REGEX_ERROR;
g_stValueTypeInfor[uVINCount].uType = IS_SPECIAL_VALUE;
g_stValueTypeInfor[uVINCount].uRange[0] = pRegex[0];
uVINCount += 1;
uOffset = 1;
}
break;
}//end switch
uOffsetSum += uOffset;
pRegex += uOffset;
}//end while
if(uVINCount > REGEX_LENGTH)
return REGEX_LENGTH_ERROR;
return REGEX_SUCCESS;
}
//正则表达式比较操作 data:待比较的数据源 uSum:待比较的数据长度
//true:ok false:fail
bool match_regex(const uint8 * data, uint8 uSum)
{
uint8 i = 0;
if(data == NULL)
return false;
while(i < uSum)
{
switch(g_stValueTypeInfor[i].uType)
{
case IS_LETTER_OR_NUMBER:
{
if( !isalnum(data[i]) )
return false;
}
break;
case IS_NUMBER:
{
if(!isdigit(data[i]))
return false;
}
break;
case IS_RANGE:
{
if((data[i] < g_stValueTypeInfor[i].uRange[0])
|| (data[i] > g_stValueTypeInfor[i].uRange[1]))
return false;
}
break;
case IS_SPECIAL_VALUE:
{
if(data[i] != g_stValueTypeInfor[i].uRange[0])
return false;
}
break;
default:
return false;
}//end switch
i += 1;
if(i == REGEX_LENGTH - 1)
return true;
}//end while
return true;
}
测试代码
///测试代码///
#include "regex_analysis.h"
#include <Windows.h>
#include <stdio.h>
#include <string.h>
int main()
{
uint8 str[] = "(\\w\\w)4A S-E2\\w{6}[0-9]{5}";
uint8 VIN[] = "(LL)4A S-E2A2EJ1085732";//LL4ASE2A2EJ1085732
if(REGEX_SUCCESS == compile_regex(str) )
{
printf("compile success!\n");
if(match_regex(VIN,(uchar)strlen((char*)VIN)))
printf("match!\n");
else
printf("not match!\n");
}
else
printf("compile fail!\n");
system("pause");
return 0;
}