如何解析多重括号,?

66i88 2019-11-07 05:37:05
比如,类似这样的表达式,
8 +(7 * (6 + 2 * (3 + 4)- 5)- 2) * 9
怎么解析呢?
谢谢
...全文
679 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
用户 昵称 2020-09-04
  • 打赏
  • 举报
回复
把我之前抄的代码贴一下看看


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;
}
tiger波波 2019-11-26
  • 打赏
  • 举报
回复
用递归函数试试,碰到左括号就递归解括号里的公式 8 +(7 * (6 + 2 * (3 + 4)- 5)- 2) * 9 7 * (6 + 2 * (3 + 4)- 5)- 2 6 + 2 * (3 + 4)- 5 3 + 4
lgstudyvc 2019-11-25
  • 打赏
  • 举报
回复
先乘除后加减,先算括号内的;纯数学的
zgl7903 2019-11-07
  • 打赏
  • 举报
回复
孤客天涯 2019-11-07
  • 打赏
  • 举报
回复
这个比较复杂,你可以网上找找表达式相关的东西,网上有个开源的,不错的,叫MTParser

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧