c实现极简单的正则表达式解析

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;
}



  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值