式の評価 (2) | c++ | スタック

1. トピックの説明

問題の説明

  変数を含む中置式は、一般的な数式です。指定された変数が 8 文字以下の小文字で構成されている場合、end は予約語であり、プログラム セグメントの終了を示します。指定された変数の値が出力され、より複雑な式 (つまり、順番に実行できる一連のステートメント) を設計できることを示します。たとえば、次のステートメントがあるとします。

abc=10
def=8
c=abc+def
abc=abc+5-c*2
? c
? abc
の終わり

出力は次のとおりです。

c=18
abc=-21

注:プログラミングの実装を簡素化するために、演算子は +、-、*、/、%、および ^ (指数演算) のみで、括弧 () は処理可能であり、入力演算式は正しいものと見なされます。

要件:スタック構造を使用して実装されています。

入力:式のシーケンス

出力:指定されたすべての変数の値

式のすべての評価は整数に評価されます。計算中に除数が 0 の場合、出力: Divide 0.

特殊なケースの説明:
式で、オペランドが負の数 (-8 など) の場合、特別な注意を払う必要があります。例:
10 プラス -8 は、10+-8 として表されます。
10 マイナス -8 は、10--8 として表されます。

 

テスト入力 期待される出力 制限時間 メモリ制限 余分なプロセス
テスト ケース 1 テキストとして表示
  1. abc=10↵
  2. デフォルト=8↵
  3. c=abc+def↵
  4. abc=abc+5-c*2↵
  5. ? c↵
  6. ? abc↵
  7. 終了↵
テキストとして表示
  1. c=18↵
  2. abc=-21↵
1秒 64M 0
テスト ケース 2 テキストとして表示
  1. a=12↵
  2. b=5↵
  3. c=a/b↵
  4. d=(a+1)%(b+1)↵
  5. e=a^2↵
  6. f=-12+a↵
  7. g=(a+5)*dc↵
  8. ? c↵
  9. ? d↵
  10. ? e↵
  11. ? f↵
  12. ? g↵
  13. a=a+10↵
  14. ? a↵
  15. 終了↵
テキストとして表示
  1. c=2↵
  2. d=1↵
  3. e=144↵
  4. f=0↵
  5. g=15↵
  6. a=22↵
1秒 64M 0
テスト ケース 3 テキストとして表示
  1. abc=3↵
  2. ab=2^(abc-1)^(5-abc)↵
  3. ? ab↵
  4. 終了↵
テキストとして表示
  1. ab=16↵
1秒 64M 0
テスト ケース 4 テキストとして表示
  1. a=2↵
  2. b=a^(a+1)^(10-8)↵
  3. ? b↵
  4. 終了↵
テキストとして表示
  1. b=512↵
1秒 64M 0
テスト ケース 5 テキストとして表示
  1. a=10↵
  2. ? a↵
  3. b=-10+10↵
  4. ? b↵
  5. a=-10-10↵
  6. ? a↵
  7. c=a+-10+-10↵
  8. ? c↵
  9. d=-20+-8-8↵
  10. ? d↵
  11. e=a-12*-2↵
  12. ? e↵
  13. f=80--10+2↵
  14. ? f↵
  15. g=-10~-10↵
  16. ? g↵
  17. h=-10+-10↵
  18. ? h↵
  19. i=(90)↵
  20. ? 私↵
  21. k=(-100)↵
  22. ? k↵
  23. 終了↵
テキストとして表示
  1. a=10↵
  2. b=0↵
  3. a=-20↵
  4. c=-40↵
  5. d=-36↵
  6. e=4↵
  7. f=92↵
  8. g=0↵
  9. h=-20↵
  10. i=90↵
  11. k=-100↵
1秒 64M 0
テスト ケース 6 テキストとして表示
  1. abcdefgh=4↵
  2. 10=10↵
  3. a=18-32↵
  4. ? a↵
  5. b=18/abcdefgh↵
  6. ? b↵
  7. c=18%(b-1)↵
  8. ? c↵
  9. d=10+(10+10)*abcdefgh↵
  10. ? d↵
  11. e=10-2*10/abcdefgh↵
  12. ? e↵
  13. f=(18-3)*3↵
  14. ? f↵
  15. 十=十*(十)↵
  16. ? テン↵
  17. 十=十/10↵
  18. 10=(10+2)/(8-10)↵
  19. ? テン↵
  20. h=(2*3)/(5*2)↵
  21. ? h↵
  22. 10=10↵
  23. x=10-(80-30)/3*3+abcdefgh↵
  24. y=(((2+8)*2-(2+abcdefgh)/2)*2-8)*2↵
  25. z=(((8+2)*(abcdefgh/2)))↵
  26. ? ×↵
  27. ? y↵
  28. ? z↵
  29. 終了↵
テキストとして表示
  1. a=-14↵
  2. b=4↵
  3. c=0↵
  4. d=90↵
  5. e=5↵
  6. f=45↵
  7. 10=100↵
  8. 10=-6↵
  9. h=0↵
  10. x=-34↵
  11. y=52↵
  12. z=20↵
1秒 64M 0

2. 思考のヒント

1. 入力から始める

入力は複数の行で構成され、次の 3 つのタイプに分けることができます。

①従来の代入式または等号四則演算

②クエスチョンマークは出力したい変数の値を表します

③終了

2.変数について

ストレージに構造体を使用することを検討してください。

#define N 110
typedef struct {
	string name;
	int value;
} VRBL;
VRBL v[N];

        VRBL が構造体であることを宣言します。各 v は変数を表し、v.name は変数の名前、v.value は変数の現在の値です。

これは非常に便利で、本当に清潔で衛生的です。

3. 4つの操作について

それはまだスタックであり、多くのトピックを行ってきたので、ここでは繰り返しません。

3. 完全なコード

このトピックはオプションですが、難易度的にはそれほど難しいものではありません。

#include<bits/stdc++.h> 
using namespace std;
#define N 110
typedef struct {
	string name;    //name是变量的名字,例如abc,e等。
	int value;      //value是变量的值。
} VRBL;
VRBL v[N];

//若返回值大于1,表示运算符;若返回1,表示是数字;若返回0,表示既不是运算符也不是数字,也就是字母。注意,这里面是不考虑等于号的。
int valu(char c) {
	if ( c==')' )					  return 6;
	if ( c=='^' ) 					  return 5;
	if ( c=='*' || c=='/' || c=='%' ) return 4; 
	if ( c=='+' || c=='-' ) 		  return 3;
	if ( c=='(' ) 					  return 2;
	if ( c>='0' && c<='9' )			  return 1;
									  return 0; 
}

//两个数之间的计算
void cal(int *a1, int a2, char op) {
	switch (op){
		case '+': (*a1) = (*a1) + a2; break;
		case '-': (*a1) = (*a1) - a2; break;
		case '*': (*a1) = (*a1) * a2; break;
		case '/': (*a1) = (*a1) / a2; break;
		case '%': (*a1) = (*a1) % a2; break;
		case '^': (*a1) = pow((*a1),a2); break;
	}
}

int main(){
	
	int valu(char);
	void cal(int*, int ,char);
	
	string Formula;
	int n=0;	//n用来统计变量的个数 
	while (cin>>Formula,Formula!="end") {
		
        //如果是问号
		if (Formula.find('?')!=-1) {
			
			cin >> Formula;
			//遍历一次v,找到相应的变量
			int i;
			for (i=0;i<=n;i++) {
				if (Formula==v[i].name) {
					break;
				}
			}
			cout << v[i].name << '=' << v[i].value << endl;
		}
		
		else {
			//执行通常的赋值或计算
			int target, digit=0; //digit用来遍历Formula,target是待赋值的变量 
			string tpry;         //tpry用来暂时存放读入的字符串内容 
			
			//找到待赋值的变量 
			while (Formula[digit]!='=') {
				tpry+=Formula[digit];
				digit++;
			} digit++;
			
			//将待赋值的变量在v中进行匹配,如果已经有了就直接套用,否则就加入新的 
			if (n==0) {
				target = 0;
				v[0].name = tpry;
				n++;
			}
			else {
				int flag=0;
				for (int i=0;i<n;i++) {
					if (tpry==v[i].name) {
						flag=1;
						target = i;
						break;
					}
				} 
				if (flag==0) {
					target = n;
					v[n].name = tpry;
					n++;
				}
			}
			
			//计算等号后面的内容
			stack<int> Svalue;	//Svalue用来存储值 
			stack<char> Sop;	//Sop用来存储运算符 
			
			int len = Formula.length(), start=digit, flag=1; //flag用来标记正负数
			while ( digit<len ) {
				
				if ( valu( Formula[digit] )==1 )
				//数字 
				{ 
					int cnt=0;
					while ( digit<len && valu(Formula[digit])==1 ) {
						cnt = cnt * 10 + Formula[digit] - '0';
						digit++;
					}
					Svalue.push(cnt*flag);
					flag=1;
				}
				
				else if ( valu( Formula[digit] )>1 )
				//运算符
				{
					if ( Sop.size()==0 ) {
						if (digit==start && Formula[digit]=='-') flag = -1;
						else Sop.push( Formula[digit] );	
					}
					else {
						//Sop不为空
						//负数 
						if ( digit>start && Formula[digit]=='-' && valu(Formula[digit-1])>1 ) {
							flag=-1;
						}
						
						//左括号 
						else if (Formula[digit]=='(' ) {
							Sop.push( Formula[digit] ); 
						}
						
						//右括号
						else if (Formula[digit]==')' ) {
							while ( Sop.size() && Sop.top()!='(' ) {								
								char c = Sop.top();	Sop.pop();
								int a = Svalue.top(); Svalue.pop();
								cal(&Svalue.top(), a, c);
							} 
							Sop.pop();
						}
						
						else {
                            //连续乘方
							if ( Sop.size() && Formula[digit]=='^' && Sop.top()=='^' ) {
								Sop.push('^');
							}
							else {
								if ( Sop.size() && valu(Formula[digit])<=valu(Sop.top()) ) {
									while ( Sop.size() && valu(Formula[digit])<=valu(Sop.top()) ) {
										char c = Sop.top();	Sop.pop();
										int a = Svalue.top(); Svalue.pop();
										cal(&Svalue.top(), a, c);
									}
									Sop.push(Formula[digit]);
								}
								else {
									Sop.push(Formula[digit]);
								}
								
							}
						}	
										 
					}
					digit++;
				}
				
				else if ( valu( Formula[digit] )==0 )
				//字母 
				{
					//找到完整的变量名称
					string word;
					while ( digit<len && valu(Formula[digit])==0 ) {
						word += Formula[digit];
						digit++;
					}
					//匹配并且取值,将其值存入栈
					for (int i=0;i<n;i++) {
						if (v[i].name==word) {
							Svalue.push(v[i].value*flag);
							flag=1;
							break;
						}
					}
				}	
			}

			//补刀
			while ( Sop.size() ) {
				int a = Svalue.top(); Svalue.pop();
				cal(&Svalue.top(), a, Sop.top());
				Sop.pop();
			}
			
			//为目标变量赋新值
			v[target].value = Svalue.top(); 
			
		}
	}
	
	return 0;
}

おすすめ

転載: blog.csdn.net/m0_70241024/article/details/127093358