//逆ポーランド記法プログラム
class Polish{
public :
enum ESize{
STACK_SIZE = 20 ,
MAX_BUF = 256 ,
};
private :
string text;
int index;
int stack[STACK_SIZE+1]; //演算スタック
int stack_count; //スタックカウンタ
string out; //出力
public :
Polish( string _text )
{
text = _text;
index = 0;
out = "";
memset( stack , 0 , sizeof( stack ) );
stack_count = 1;
}
//スタックに値をセットしてスタックカウンタをカウント
void push( int c )
{
stack_count++; //スタックを進める
stack[stack_count] = c; //プッシュする
}
//スタックの値を一つ取り出してスタックカウンタを減らす
int pop()
{
int result = stack[stack_count]; //戻り値に現在のスタックを
stack_count--; //スタックを一つ落とす
return result; //出力
}
//演算子の強さリスト
int order( int c )
{
switch( c ){
/*
一番強い
*/
case '*' :
case '/' :
return 3;
/*
次に強い
*/
case '+' :
case '-' :
return 2;
/*
括弧は特殊扱い
*/
case '(' :
case ')' :
return 1;
}
return 0;
}
//括弧開始点を発見したとき
void findLeftParam()
{
push( text[index] ); //プッシュする
}
//括弧の閉じを発見する
void findRightParam()
{
while( true ){ //'('を発見するまでのパラメータを出力する
int c = pop();
if( c == '(' ){
break;
}
if( stack_count == 0 ){
printf( "対応する'('を発見できなかった\n" );
break;
}
out += c;
}
}
//計算式を逆ポーランド記法に変換
void AnalyzePolish()
{
while( true ){
if( index == (int)text.length() ){ //文末を見つけたら
while( stack_count > 0 ){ //貯まっているスタックを解決
out += pop();
}
break; //ループを抜ける
}
if( isdigit( text[index] ) ){ //数値であったら
out += text[index]; //出力にセット
}
//それ以外は演算子と判断する
switch( text[index] ){
//'('から')'までの
case '(' :
findLeftParam();
break;
case ')' :
findRightParam();
break;
//四則演算子
case '+' :
case '-' :
case '*' :
case '/' :
while( stack_count > 0 && order( stack[stack_count] ) >= order( text[index] ) ){ //新しく発見した演算子よりもスタックトップの演算子のほうが強い場合、
out += pop(); //先にスタックを出力しておく
}
push( text[index] ); //その後、新しい演算子をスタックに積み上げる
}
index++; //次のIndexへ...Let's Go!!
}
out += "\0";
printf( "%s\n" , out.c_str() );
}
};
void main()
{
Polish polish( "(3*5) + (2*3)" );
polish.AnalyzePolish();
}
0から9までの数値しか使えないですが
逆ポーランド記法のアルゴリズムを勉強するぶんには最初はこれくらいの規模がわかりやすいですね。
ではでは