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个字符的任何字符串匹配
[‘sss…s’] 与单引号中的字符串匹配
如要匹配“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
万事俱备,现在进行模式匹配。
- 2014年7月7日星期一(DEMO8-7使用新的模型格式)
- 2014年7月8日星期二(DEMO8-8加载3DSMAX ASCII格式模型.ASC)
- 2014年3月3日星期一(DEMO8-3,ALPHA混合)
- 2014年3月7日星期五(DEMO8-4,实体三角形着色)
- 2010年6月7日(新公司入职,第十周星期一)
- 2007年7月2日 星期一
- 2007年7月23日 星期一
- 2017年8月7日 星期一
- 2013年9月11日星期三(demo8-7,三角形)
- 2014年8月26日星期二(DEMO8-9加载COB模型)
- 2013年1月7日 星期一 GTD 稳
- 2014年2月22日星期六(DEMO8-1,颜色与放缩系数相乘)
- 2014年2月25日星期二(DEMO8-2,光照图调制)
- 2014年3月8日星期六(DEMO8-5恒定着色)
- 2014年3月9日星期日(DEMO8-6,画家算法)
- 2012年1月9日 星期一(oracle读书笔记,PL/SQL程序触发器的使用)
- 2010年4月19日(新公司入职,第三周星期一)
- 2010年4月26日(新公司入职,第四周星期一)
- 2014秋C++ 第15周项目3参考解答 在OJ上玩指针
- 树链剖分小结,模板
- Codility上的问题 (40) Phosphorus 2014
- python杂记
- 机器视觉开源处理库汇总-介绍n款计算机视觉库/人脸识别开源库/软件 -几种图像处理类库的比较-视觉相关网站
- 2014年7月7日星期一(DEMO8-7使用新的模型格式)
- 转载:Why does MYSQL higher LIMIT offset slow the query down?
- 2014年7月8日星期二(DEMO8-8加载3DSMAX ASCII格式模型.ASC)
- poj3253 Fence Repair(哈弗曼)
- win7下VC++6.0打开多个工作区间
- 2014年8月26日星期二(DEMO8-9加载COB模型)
- 机器视觉专题
- [LeetCode] Balanced Binary Tree 平衡二叉树
- 9-2加上光照计算的GOURAUD shader多边形)