2014年7月7日星期一(DEMO8-7使用新的模型格式)

原来觉得很简单,是个控制台程序,后来发现实际上不这么简单。慢慢分析吧,

先加个类,CPARSERV1

#pragma once

 

#define            PARSER_BUFFER_SIZE                   256

#define            PARSER_DEFAULT_COMMENT               "#"

#define            PARSER_MAX_COMMENT                   16

 

class CPARSERV1

{

public:

     CPARSERV1(void);

     ~CPARSERV1(void);

 

public:

     //打开文件

     int           Open( char * filename );

     //重置文件系统

     int           Reset();

 

 

public:

     FILE *    fstream;                    //文件指针

     char     buffer[PARSER_BUFFER_SIZE]; //缓冲区

     int           length;                          //当前行长度

     int           num_lines;                       //处理了多少行

     char     comment[PARSER_MAX_COMMENT];

 

 

 

 

};

逐步进行,首先是构造函数和析构函数

 

CPARSERV1::CPARSERV1(void)

{

     fstream                     = NULL;

     Reset();

}

 

CPARSERV1::~CPARSERV1(void)

{

     Reset();

}

看看RESET()中有什么内容,

 

打开文件,

 

int CPARSERV1::Open( char * filename )

{

     Reset();

 

     if ( ( fstream = fopen( filename, "r")) != NULL )

     {

         return 1;

     }

     else

     {

         return 0;

     }

}

下面进行读取一行文本

有几个模式,首先定义下:

 

#define            PARSER_STRIP_EMPTY_LINES             1             //删除空行

#define            PARSER_LEAVE_EMPTY                   2             //保留空行

#define            PARSER_STRIP_WS_ENDS                 4             //删除行尾的空格

#define            PARSER_LEAVE_WS_ENDS                 8             //保留行尾的空格

#define            PARSER_STRIP_COMMENTS                16            //删除注释

#define                                            PARSER_LEAVE_COMMENTS                32            //保留注释

 

 

//重置系统

int CPARSERV1::Reset()

{

     if (fstream)

     {

         fclose(fstream);

     }

     fstream                                   = NULL;

     memset( buffer, 0, sizeof(buffer));

     length                                    = 0;

     num_lines                            = 0;

     strcpy(comment, PARSER_DEFAULT_COMMENT);

 

     return 1;

}

//关闭文件

int CPARSERV1::Close()

{

     return ( Reset());

}

//读取下一行,如果有,则返回该行;如果没有,返回NULL

char * CPARSERV1::GetLine( int mode )

{

     char     *    string;

     if (fstream)

     {

         if ( mode & PARSER_STRIP_EMPTY_LINES )

         {

              while( 1)

              {

                   if ( ( string = fgets( buffer, PARSER_BUFFER_SIZE, fstream)) == NULL )

                   {

                       break;

                   }

 

                   int           slength                     = strlen( string );

                   int           sindex                      = 0;

 

                   while( isspace( string[sindex]))

                   {

                       sindex   ++;

                   }

                   if ( ( slength - sindex ) > 0 )

                   {

                       memmove( ( void * ) buffer, ( void * ) & string[sindex], ( slength - sindex) + 1 );

                       string                               = buffer;

                       slength                              = strlen( string );

 

                       if ( mode & PARSER_STRIP_COMMENTS )

                       {

                            char *    comment_string     = strstr( string, comment );

                            if ( comment_string == NULL )

                            {

                                 break;

                            }

 

                            int           cindex             = ( int ) ( comment_string - string );

 

                            if ( cindex == 0 )

                            {

                                 continue;;

                            }

                            else

                            {

                                 comment_string[0]      = 0;

                                 break;

                            }

 

                       }

                       break;

                   }

              }

         }

         else

         {

              string                               = fgets( buffer, PARSER_BUFFER_SIZE, fstream );

 

         }

 

         if ( string )

         {

              num_lines ++;

 

              if ( mode & PARSER_STRIP_WS_ENDS )

              {

                   StringLtrim( buffer );

                   StringRtrim( buffer );

              }

              length                               = strlen( buffer );

 

              return string;

         }

         else

         {

              return NULL;

         }

 

     }

     else

     {

         return NULL;

 

 

     }

 

 

}

 

 

//去掉左空格

char * CPARSERV1::StringLtrim( char * string )

{

     int           sindex             = 0;

     int           slength            = strlen( string );

 

     if ( !string || slength == 0 )

     {

         return string;

     }

 

     while( isspace(string[sindex]) && sindex < slength )

     {

         string[sindex ++ ]     = 0;

     }

     memmove( ( void * )string, ( void * ) & string[sindex], ( slength - sindex ) + 1 );

 

     return string;

}

 

//去掉右空格

char * CPARSERV1::StringRtrim( char * string )

{

     int           sindex             = 0;

     int           slength            = strlen( string );

 

     if ( !string || slength == 0 )

     {

         return string;

     }

 

     sindex                           = slength - 1;

     while( isspace(string[sindex]) && sindex >= 0 )

     {

         string[sindex-- ]      = 0;

     }

 

     return string;

}

 

先弄个简单的,设置注释字符串,比如“#”、“;”和“//”,很简单, 就是长度不足,则用字符串代替

 

int CPARSERV1::SetComment(char *string)

{

     if( strlen( string ) < PARSER_MAX_COMMENT )

     {

         strcpy( comment, string );

         return ( 1 );

     }

     else

         return ( 0 );

}

 

应该模式匹配是最重要的了,不过,先进行下外围吧,辅助函数

字符剔除函数

 

int CPARSERV1::StripChars(char *string_in, char *string_out, char *strip_chars, int case_on )

{

     int           num_extracts       = 0,                                 //删除的字符个数

                   index_in           = 0,                                 //输入的当前索引

                   index_out          = 0,                                 //输出的当前索引

                   sindex,                                                          //循环变量

                   slength                = strlen( strip_chars );             //删除的字符串长度

 

     //错误检测

     if( !string_in || !string_out || strlen( string_in ) == 0 )

         return ( 0 );

 

     //如果没有可替换的

     if( !strip_chars || strlen( strip_chars ) == 0 )

     {

         strcpy( string_out, string_in );

         return ( 0 );

     }

 

     //决定情况是否重要

     if( case_on == 1 )

     {

         //逐字符串拷贝

         while( string_in[index_in] )

         {

              for( sindex = 0; sindex < slength; sindex++ )

              {

                   if( string_in[index_in] == strip_chars[sindex] )

                   {

                       //跳过该输入字符(它被删除了)

                       index_in ++;

                       num_extracts ++;

                       break;

                   }

}

                   //删除字符串是否找到?

                   if( sindex >= slength )

                   {

                       string_out[index_out++]     = string_in[index_in++];

                   }

 

             

         }

 

     }

     else

     {

         //不敏感的情况下逐字符串拷贝

         while( string_in[index_in] )

         {

              for( sindex = 0; sindex < slength; sindex++ )

              {

                   if( toupper( string_in[index_in] ) == toupper( strip_chars[sindex] ) )

                   {

                       //跳过该输入字符(它被删除了)

                       index_in ++;

                       num_extracts ++;

                       break;

                   }

              }

                   //删除字符串是否找到?

                   if( sindex >= slength )

                   {

                       string_out[index_out++]     = string_in[index_in++];

                   }

 

             

         }

     }

 

     //消除输出字符串

     string_out[index_out]                          = 0;

 

     return num_extracts;

 

}

 

下面进行替换字符串中的字符函数,主要是在StripChars的基础上,再加上指定字符,将其隔开,因此多了个char参数

 

 

int CPARSERV3::ReplaceChars(char *string_in, char *string_out, char *replace_chars, char rep_char, int case_on )

{

     int           num_replacements   = 0,                                 //删除的字符个数

         index_in           = 0,                                 //输入的当前索引

         index_out          = 0,                                 //输出的当前索引

         sindex,                                                          //循环变量

         slength                = strlen( replace_chars );           //删除的字符串长度

 

     //错误检测

     if( !string_in || !string_out || strlen( string_in ) == 0 )

         return ( 0 );

 

     //如果没有可替换的

     if( !replace_chars || strlen( replace_chars ) == 0 )

     {

         strcpy( string_out, string_in );

         return ( 0 );

     }

 

     //决定情况是否重要

     if( case_on == 1 )

     {

         //逐字符串拷贝

         while( string_in[index_in] )

         {

              for( sindex = 0; sindex < slength; sindex++ )

              {

                   if( string_in[index_in] == replace_chars[sindex] )

                   {

                       //替换之

                       string_out[index_out++]     = rep_char;

                       index_in ++;

                       num_replacements ++;

                       break;

                   }

              }

                   //删除字符串是否找到?

                  if( sindex >= slength )

                   {

                       string_out[index_out++]     = string_in[index_in++];

                   }

 

             

         }

 

     }

     else

     {

         //不敏感的情况下逐字符串拷贝

         while( string_in[index_in] )

         {

              for( sindex = 0; sindex < slength; sindex++ )

              {

                   if( toupper( string_in[index_in] ) == toupper( replace_chars[sindex] ) )

                   {

                       //替换之

                       string_out[index_out++]          = rep_char;

                       index_in ++;

                       num_replacements ++;

                       break;

                   }

              }   

                   //删除字符串是否找到?

                   if( sindex >= slength )

                   {

                       string_out[index_out++]     = string_in[index_in++];

                   }

 

             

         }

     }

 

     //消除输出字符串

     string_out[index_out]                          = 0;

 

     return num_replacements;

}

下面判断字符串是否可以转为浮点数,如果可以,则返回转换后的值,前提是对于

[空格][符号][.][{d|D|e|E}[符号]数字]模式的

 

float CPARSERV1::IsFloat(char *fstring)

{

     char *   string                                    = fstring;

 

     //空格

     while( isspace( * string ) )

         string ++;

 

     //符号

     if( * string == '+' || *string == '-' )

         string++;

 

     //符号

     while( isdigit( *string ) )

         string++;

 

     //[.]

     if( *string == '.' )

     {

         string++;

         while( isdigit( * string ) )

              string++;

     }

 

     //[{d|D|e|E}[符号]数字]

 

     if( * string == 'e' || *string == 'E' || * string == 'd' || * string == 'D' )

     {

         string ++;

 

         //符号

         if( * string == '+' || * string == '_' )

              string ++;

 

         //[数字]

         while( isdigit( * string ) )

              string++;

     }

 

     //经过上述处理后,如果到达了字符串末尾,则可以转换为浮点数,否则,不是浮点数

     if( strlen( fstring ) == ( int ) ( string - fstring ) )

         return atof( fstring );

     else

                                               return FLT_MIN;

}

 

 

下面进行将字符串转换为整数

 

int CPARSERV1::isInt(char *fstring)

{

     char *   string                                    = fstring;

 

     //空格

     while( isspace( * string ) )

         string ++;

 

     //符号

     if( * string == '+' || *string == '_' )

         string++;

 

     //[数字]

     while( isdigit( * string ) )

         string++;

    

 

     //经过上述处理后,如果到达了字符串末尾,则可以转换为浮点数,否则,不是浮点数

     if( strlen( fstring ) == ( int ) ( string - fstring ) )

         return atoi( fstring );

     else

         return INT_MIN;

}

 

下面进行本DMEO最难的地方,模式匹配了。即在传入的字符串中查找与传入的模式匹配的字串,

首先定义存储空间,用来存储字符串、浮点数或者整数

//模式匹配参数存储空间

     //函数patter()返回时,匹配的内容将存储在这些数组中,

 

     //匹配任何字符串

     char     pstrings[PATTERN_MAX_ARGS][PATTERN_BUFFER_SIZE];       

     int           num_pstrings;

 

     //匹配任何浮点数

     float         pfloats[PATTERN_MAX_ARGS];                                  

     int           num_pfloats;

 

     //匹配任何整数

     int           pints[PATTERN_MAX_ARGS];

     int           num_pints;

 

模式匹配语言有以下几种

[i]            与整数匹配

[f]            与浮点数匹配

[s=d]          与包含d个字符的任何字符串匹配

[s<d]          与长度小于d个字符的任何字符串匹配

[s>d]          与长度大于d个字符的任何字符串匹配

[ssss]      与单引号中的字符串匹配

 

如要匹配“vertex: 34.56 23.67 10.90可使用“[vertex][f][f][f],此时num_floats=3,pfloats[]={34.56,23.67,10.90}.

模式匹配语言实现就是如下所示

 

int CPARSERV1::Pattern_Match(char *string, char *pattern, ...)

{

     char          token_type[PATTERN_MAX_ARGS];                               //类型,f,i,s,l

     char          token_string[PATTERN_MAX_ARGS][PATTERN_BUFFER_SIZE];    //逐个字符串

     char          token_operator[PATTERN_MAX_ARGS];                            //>,<,,=等等

     int                token_numeric[PATTERN_MAX_ARGS];                        //一些数字

     char          buffer[PARSER_BUFFER_SIZE];                                  //工作缓冲

 

     //一些错误测试

     if( ( !string || strlen( string ) == 0 )|| ( !pattern || strlen( pattern ) == 0 ) )

         return 0;

 

     //将行拷贝进工作区域

     strcpy( buffer, string );

     int                tok_start                   = 0,

                       tok_end                          = 0,

                       tok_restart                      = 0,

                       tok_first_pass                   = 0,

                       num_tokens                       = 0;

 

     //第一步,消除列表

     while( 1 )

     {

         //消除空格

         while( isspace( pattern[tok_start] ) )

              tok_start ++;

 

         //行结束了么?

         if( tok_start >= strlen( pattern ) )

              break;

 

         //寻找开始匹配'['

         if( pattern[tok_start] == '[' )

         {

              //现在开始寻找匹配字符

              switch( pattern[tok_start + 1] )

              {

              case PATTERN_TOKEN_FLOAT:        //浮点数

                   {

                       //确认匹配格式正确有''就有''

                       if( pattern[tok_start + 2] != ']' )

                            return 0;

 

                       //向前推动个

                       tok_start                   += 3;

                       //将类型中插入一个浮点数

                       token_type[num_tokens]      = PATTERN_TOKEN_FLOAT;

                       strcpy( token_string[num_tokens], "" );

                       token_operator[num_tokens]  = 0;

                       token_numeric[num_tokens]   = 0;

                       num_tokens++;

#ifdef PARSER_DEBUG_ON

                       printf("\n浮点数寻找" );

#endif

                   }

                   break;

 

              case PATTERN_TOKEN_INT: //整数

                   {

                       //确认匹配格式正确有''就有''

                       if( pattern[tok_start + 2] != ']' )

                            return 0;

 

                       //向前推动个

                       tok_start                   += 3;

                       //将类型中插入一个整数

                       token_type[num_tokens]      = PATTERN_TOKEN_INT;

                       strcpy( token_string[num_tokens], "" );

                       token_operator[num_tokens]  = 0;

                       token_numeric[num_tokens]   = 0;

                       num_tokens++;

#ifdef PARSER_DEBUG_ON

                       printf("\n整数寻找" );

#endif

                   }

                   break;

 

              case PATTERN_TOKEN_LITERAL: //Literal字符串

                   {

 

                       //向前推动个

                       tok_start                   += 2;

                       tok_end                          = tok_start;

 

                       //消除字符串

                       while( pattern[tok_end] != PATTERN_TOKEN_LITERAL )

                            tok_end++;

                       //确认匹配格式正确有''就有''

                       if( pattern[tok_end + 1] != ']' )

                            return 0;

 

 

                       //literal字符串从(tok_start到(tok_end-1)

                       memcpy( token_string[num_tokens], & pattern[tok_start], ( tok_end - tok_start ) );

                       token_string[num_tokens][( tok_end - tok_start)]   = 0;

 

                       //将类型中插入一个整数

                       token_type[num_tokens]      = PATTERN_TOKEN_LITERAL;

                       token_operator[num_tokens]  = 0;

                       token_numeric[num_tokens]   = 0;

#ifdef PARSER_DEBUG_ON

                       printf("\n找到的LITERAL字符串=%s", token_string[num_tokens] );

#endif

                       tok_start                   = tok_end + 2;

                       num_tokens++;

 

                   }

                   break;

 

 

              case PATTERN_TOKEN_STRING:  //变长ASCII字符串

                   {

 

                       if( pattern[tok_start + 2] == '=' || pattern[tok_start + 2] == '>' || pattern[tok_start + 2] == '<' )

                       {

                            tok_end                          = tok_start + 3;

 

                      

                            while( isdigit( pattern[tok_end] ) )

                                 tok_end++;

                       //确认匹配格式正确有''就有''

                       if( pattern[tok_end ] != ']' )

                            return 0;

 

 

                       //ASCII字符串拷贝,兵转换为实数

                       memcpy( buffer, & pattern[tok_start + 3], ( tok_end - tok_start ) );

                       buffer[tok_end - tok_start] = 0;

 

                       //将类型中插入一个字符串

                       token_type[num_tokens]      = PATTERN_TOKEN_STRING;

                       strcpy( token_string[num_tokens], "" );

                       token_operator[num_tokens]  = pattern[tok_start + 2];

                       token_numeric[num_tokens]   = atoi( buffer );

#ifdef PARSER_DEBUG_ON

                       printf("\n找到的字符串comparator=%s, characters: %d", token_operator[num_tokens], token_numeric[num_tokens] );

#endif

                       tok_start                   = tok_end + 1;

                       num_tokens++;

 

                   }

                   break;

 

              default:

                   break;

              }

         }

 

         if( tok_start >= strlen( pattern ) )

              break;

     }

 

#ifdef PARSER_DEBUG_ON

     printf( "\n 字符串:%s", string );

     printf( "\n扫描类型:%s", pattern );

     printf( "\n数目:%d",num_tokens );

#endif

 

     //此时,我们有了需要寻找的类型,于是寻找之

     int           pattern_state      = PATTERN_STATE_INIT;       //初始状态

     int           curr_tok           = 0;                       

     char     token[PATTERN_BUFFER_SIZE];

 

     //输入扫描状态机

      while( 1 )

      {

          switch( pattern_state )

          {

 

          case PATTERN_STATE_INIT:

               {

                    //模式初始状态

                    strcpy( buffer, string );

 

                    tok_start             = 0;

                    tok_end           = 0;

                    tok_restart       = 0;

                    tok_first_pass        = 1;

                    curr_tok          = 0;

 

                    //重置输出队列

                    num_pints             = num_pfloats          = num_pstrings              = 0;

 

                    //专项重置状态

                    pattern_state         = PATTERN_STATE_RESTART;

               }

               break;

 

          case PATTERN_STATE_RESTART:

               {

                    curr_tok          = 0;

                    tok_first_pass        = 1;

 

                    //错误检测

                    if( tok_end >= strlen( buffer ) )

                        return 0;

 

                    //重置扫描器

                    tok_start             = tok_end              = tok_restart;

 

                   pattern_state         = PATTERN_STATE_NEXT;

               }

               break;

 

          case PATTERN_STATE_NEXT:

               {

                    //看看匹配字符串是否已经匹配

                    if( curr_tok >= num_tokens )

                    {

                        pattern_state     = PATTERN_STATE_MATCH;

                    }

                    else

                    {

                        if( tok_end >= strlen( buffer ) )

                             return ( 0 );

 

                        tok_start         = tok_end;

                        while( isspace( buffer[tok_start] ) )

                             tok_start++;

                        tok_end      = tok_start;

 

                        while( !isspace( buffer[tok_end] ) && tok_end < strlen( buffer ) )

                             tok_end++;

 

                        //

                        memcpy( token, & buffer[tok_start], tok_end - tok_start );

                        token[tok_end - tok_start]                    = 0;

 

                        if( strlen( token ) == 0 )

                             return ( 0 );

 

                        //

                        if( tok_first_pass )

                        {

                             tok_first_pass                                = 0;

                             tok_restart                                   = tok_end;

                        }

 

                        //设置状态

                        switch( token_type[curr_tok] )

                        {

 

                        case PATTERN_TOKEN_FLOAT:

                             {

                                  pattern_state                            = PATTERN_STATE_FLOAT;

                             }

                             break;

 

                        case PATTERN_TOKEN_INT:

                             {

                                  pattern_state                            = PATTERN_STATE_INT;

                             }

                             break;

 

                        case PATTERN_TOKEN_STRING:

                             {

                                  pattern_state                            = PATTERN_STATE_STRING;

                             }

                             break;

 

                        case PATTERN_TOKEN_LITERAL:

                             {

                                  pattern_state                            = PATTERN_STATE_LITERAL;

                             }

                             break;

 

                        default:

                             break;

 

                        }

                    }

               }

               break;

 

          case PATTERN_STATE_FLOAT:

               {

                    float             f                                    = IsFloat( token );

 

                    if( f != FLT_MIN )

                    {

                        pfloats[num_pfloats++]                        = f;

 

                        curr_tok++;

                        pattern_state                                     = PATTERN_STATE_NEXT;

                    }

                    else

                    {

 

                        pattern_state                                     = PATTERN_STATE_RESTART;

                    }

               }

               break;

 

         case PATTERN_STATE_INT:

               {

                    int          i                                    = isInt( token );

 

                    if( i != INT_MIN )

                    {

                        pints[num_pints++]                                = i;

 

                        curr_tok++;

                        pattern_state                                     = PATTERN_STATE_NEXT;

                    }

                    else

                    {

 

                        pattern_state                                     = PATTERN_STATE_RESTART;

                    }

               }

               break;

 

                        

         case PATTERN_STATE_LITERAL:

              {

 

                    if( strcmp( token, token_string[curr_tok] ) == 0 )

                    {

                        strcpy( pstrings[num_pstrings++], token );

 

                        curr_tok++;

                        pattern_state                                     = PATTERN_STATE_NEXT;

                    }

                    else

                    {

 

                        pattern_state                                     = PATTERN_STATE_RESTART;

                    }

               }

               break;

 

         case PATTERN_STATE_STRING:

              {

                   //需要测试非空字符

                   switch( token_operator[curr_tok] )

                   {

                   case '=':

                       {

                            if( strlen( token ) == token_numeric[curr_tok] )

                            {

                                 strcpy( pstrings[num_pstrings++], token );

 

                                 curr_tok++;

 

                                 pattern_state                             = PATTERN_STATE_NEXT;

                            }

                            else

                            {

                                 pattern_state                             = PATTERN_STATE_RESTART;

                            }

                       }

                       break;

                           

                   case '>':

                       {

                            if( strlen( token ) > token_numeric[curr_tok] )

                            {

                                 strcpy( pstrings[num_pstrings++], token );

 

                                curr_tok++;

 

                                 pattern_state                             = PATTERN_STATE_NEXT;

                            }

                            else

                            {

                                 pattern_state                             = PATTERN_STATE_RESTART;

                            }

                       }

                       break;

                   case '<':

                       {

                            if( strlen( token ) < token_numeric[curr_tok] )

                            {

                                 strcpy( pstrings[num_pstrings++], token );

 

                                 curr_tok++;

 

                                 pattern_state                             = PATTERN_STATE_NEXT;

                            }

                            else

                            {

                                 pattern_state                             = PATTERN_STATE_RESTART;

                            }

                       }

                       break;

 

                   default:

                       break;

                   }

              }

              break;

 

         case PATTERN_STATE_MATCH:

              {

#ifdef PARSER_DEBUG_ON

                   printf( "\n模式:%s匹配!", pattern );

#endif

 

                   return ( 1 );

              }

              break;

 

         case PATTERN_STATE_END:

              {

              }

              break;

 

         default:

              break;

         }

     }

}

 

 

                           

 

 

//设定模式匹配的内存空间和数量

#define            PATTERN_BUFFER_SIZE                       80

#define            PATTERN_MAX_ARGS                          16

 

万事俱备,现在进行模式匹配。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值