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

来源:互联网 发布:淘宝买家具哪个品牌好 编辑:程序博客网 时间:2024/05/22 12:37

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

先加个类,CPARSERV1

#pragmaonce

 

#define           PARSER_BUFFER_SIZE                  256

#define           PARSER_DEFAULT_COMMENT              "#"

#define           PARSER_MAX_COMMENT                  16

 

classCPARSERV1

{

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()中有什么内容,

 

打开文件,

 

intCPARSERV1::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            //保留注释

 

 

//重置系统

intCPARSERV1::Reset()

{

    if (fstream)

    {

        fclose(fstream);

    }

    fstream                                  = NULL;

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

    length                                   = 0;

    num_lines                           = 0;

    strcpy(comment,PARSER_DEFAULT_COMMENT);

 

    return 1;

}

//关闭文件

intCPARSERV1::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;

}

 

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

 

intCPARSERV1::SetComment(char *string)

{

    if( strlen(string ) < PARSER_MAX_COMMENT )

    {

        strcpy( comment,string );

        return ( 1 );

    }

    else

        return ( 0 );

}

 

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

字符剔除函数

 

intCPARSERV1::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参数

 

 

intCPARSERV3::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}[符号]数字]模式的

 

floatCPARSERV1::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;

}

 

 

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

 

intCPARSERV1::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}.

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

 

intCPARSERV1::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++;

#ifdefPARSER_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++;

#ifdefPARSER_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;

#ifdefPARSER_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 );

#ifdefPARSER_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;

    }

 

#ifdefPARSER_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:

             {

#ifdefPARSER_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

 

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

0 0
原创粉丝点击