16,472
社区成员
发帖
与我相关
我的任务
分享
TCHAR *
GetExpressionValue( TCHAR *expression, __int64 *value )
{
//编写代码对算术表达式求值的经典方法由 Donald Knuth 描述于 1962 年。
//
//Knuth 将此概括为三个步骤:
//
//1.对中缀表达式进行语法分析
//2.中缀表达式到后缀表达式的转换
//3.对后缀表达式求值
TCHAR result[ 0x400 ] = _T( "" );
TCHAR stack[ 0x400 ] = _T( "" );
int top = -1;
//TCHAR end[ 30 ] = _T( ";,[]" );
//int i;
//int len;
TCHAR *p = expression;
int isfirst = 1;
//len = ( int )_tcslen( end );
TCHAR t[ 256 ] = _T( "" );
int current_len;
//中缀表达式到后缀表达式的转换
//
//
//要把表达式从中缀表达式的形式转换成用后缀表示法表示的等价表达式,必须了解操作符的优先级和结合性。
//优先级或者说操作符的强度决定求值顺序;优先级高的操作符比优先级低的操作符先求值。
//如果所有操作符优先级一样,那么求值顺序就取决于它们的结合性。
//操作符的结合性定义了相同优先级操作符组合的顺序(从右至左或从左至右)。
//
//转换过程包括用下面的算法读入中缀表达式的操作数、操作符和括号:
//
//1.初始化一个空堆栈,将结果字符串变量置空。
//2.从左到右读入中缀表达式,每次一个字符。
//3.如果字符是操作数,将它添加到结果字符串。
//4.如果字符是个操作符,弹出(pop)操作符,直至遇见开括号(opening parenthesis)、
// 优先级较低的操作符或者同一优先级的右结合符号。
// 把这个操作符压入(push)堆栈。
//5.如果字符是个开括号,把它压入堆栈。
//6.如果字符是个闭括号(closing parenthesis),在遇见开括号前,弹出所有操作符,然后把它们添加到结果字符串。
//7.如果到达输入字符串的末尾,弹出所有操作符并添加到结果字符串。
//
do
{
// gettoken( p, t, ¤t_len );
// for( i = 0; i < len; i++ )
// {
// if( t[ 0 ] == end[ i ]
// ||
// !t[ 0 ]
// )
// {
// goto EXPRESSION_BREAK;
// }
// }
p = gettoken( p, t, ¤t_len );
if( 0 == t[ 0 ] )
{
break;
}
if( isdec_t( t ) )
{
_tcscat( result, t );
_tcscat( result, g____newspace );
isfirst = 0;
}
else if( is0x_t( t ) )
{
// 转成10进制,再进行求值
int len = ( int )_tcslen( t );
__int64 k = 0;
int i;
for( i = 2; i < len; i++ )
{
k <<= 4;
if( t[ i ] >= '0' && t[ i ] <= '9' )
{
k |= t[ i ] - '0';
}
else if( t[ i ] >= 'a' && t[ i ] <= 'f' )
{
k |= t[ i ] - 'a' + 10;
}
else if( t[ i ] >= 'A' && t[ i ] <= 'F' )
{
k |= t[ i ] - 'A' + 10;
}
}
TCHAR v[ 0x20 ];
_stprintf( v, _T( "%I64u" ), k );
_tcscat( result, v );
_tcscat( result, g____newspace );
isfirst = 0;
}
else if( !_tcscmp( t, _T( "+" ) ) || !_tcscmp( t, _T( "-" ) ) )
{
if( isfirst )
{
_tcscat( result, _T( "0" ) );
_tcscat( result, g____newspace );
isfirst = 0;
}
while( -1 != top
&&
LEFT_XIAOKUOHAO != stack[ top ]
)
{
result[ _tcslen( result ) ] = stack[ top ];
_tcscat( result, g____newspace );
top--;
}
top++;
stack[ top ] = t[ 0 ];
isfirst = 0;
}
else if( !_tcscmp( t, _T( "*" ) ) || !_tcscmp( t, _T( "/" ) ) )
{
while( '*' == stack[ top ]
||
XIEGANG == stack[ top ]
)
{
result[ _tcslen( result ) ] = stack[ top ];
_tcscat( result, g____newspace );
top--;
}
top++;
stack[ top ] = t[ 0 ];
isfirst = 0;
}
else if( !_tcscmp( t, _T( "(" ) ) )
{
top++;
stack[ top ] = t[ 0 ];
isfirst = 1;
}
else if( !_tcscmp( t, _T( ")" ) ) )
{
while( LEFT_XIAOKUOHAO != stack[ top ] )
{
result[ _tcslen( result ) ] = stack[ top ];
_tcscat( result, g____newspace );
top--;
}
top--;
isfirst = 0;
}
else
{
INIT;
mul( 20 );
if( IsChinese() )
{
RED( _T( "表达式错误 " ) );
}
else
{
RED( _T( "Expression Error" ) );
}
BLUE( p );
SHOW;
//printf( "表达式错误 %s", p );
return expression;
}
} while ( 1 );
//EXPRESSION_BREAK:
while( -1 != top )
{
result[ _tcslen( result ) ] = stack[ top ];
_tcscat( result, g____newspace );
top--;
}
//后缀表达式求值
//
//对后缀表达式求值比直接对中缀表达式求值简单。
//在后缀表达式中,不需要括号,而且操作符的优先级也不再起作用了。
//您可以用如下算法对后缀表达式求值:
//
//1.初始化一个空堆栈
//2.从左到右读入后缀表达式
//3.如果字符是一个操作数,把它压入堆栈。
//4.如果字符是个操作符,弹出两个操作数,执行恰当操作,然后把结果压入堆栈。如果您不能够弹出两个操作数,后缀表达式的语法就不正确。
//5.到后缀表达式末尾,从堆栈中弹出结果。若后缀表达式格式正确,那么堆栈应该为空。
double data[ 64 ];
TCHAR *q = result;
memset( data, 0, sizeof( data ) );
top = -1;
do
{
q = gettoken( q, t, ¤t_len );
if( !t[ 0 ] )
{
break;
}
if( !_tcscmp( t, _T( "+" ) ) )
{
data[ top - 1 ] += data[ top ];
top--;
}
else if( !_tcscmp( t, _T( "-" ) ) )
{
data[ top - 1 ] -= data[ top ];
top--;
}
else if( !_tcscmp( t, _T( "*" ) ) )
{
data[ top - 1 ] *= data[ top ];
top--;
}
else if( !_tcscmp( t, _T( "/" ) ) )
{
if( !data[ top ] )
{
*value = 0xffffffffffffffff;
return p;
}
else
{
data[ top - 1 ] /= data[ top ];
top--;
}
}
else
{
top++;
if( isdec_t( t ) )
{
data[ top ] = ( double )_wtoi64( t );
#if 0
size_t i;
size_t l = _tcslen( t );
double d = 0.0;
for( i = 0; i < l; i++ )
{
d *= 10.0;
d += ( t[ i ] - 0x30 );
}
data[ top ] = d;
#endif
}
else
{
INIT;
mul( 20 );
if( IsChinese() )
{
RED( _T( "表达式错误 " ) );
}
else
{
RED( _T( "Expression Error" ) );
}
BLUE( p );
SHOW;
return expression;
}
}
} while( 1 );
*value = ( __int64 )data[ top ];
return p;
}