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 テキストとして表示
- abc=10↵
- デフォルト=8↵
- c=abc+def↵
- abc=abc+5-c*2↵
- ? c↵
- ? abc↵
- 終了↵
テキストとして表示
- c=18↵
- abc=-21↵
1秒 64M 0 テスト ケース 2 テキストとして表示
- a=12↵
- b=5↵
- c=a/b↵
- d=(a+1)%(b+1)↵
- e=a^2↵
- f=-12+a↵
- g=(a+5)*dc↵
- ? c↵
- ? d↵
- ? e↵
- ? f↵
- ? g↵
- a=a+10↵
- ? a↵
- 終了↵
テキストとして表示
- c=2↵
- d=1↵
- e=144↵
- f=0↵
- g=15↵
- a=22↵
1秒 64M 0 テスト ケース 3 テキストとして表示
- abc=3↵
- ab=2^(abc-1)^(5-abc)↵
- ? ab↵
- 終了↵
テキストとして表示
- ab=16↵
1秒 64M 0 テスト ケース 4 テキストとして表示
- a=2↵
- b=a^(a+1)^(10-8)↵
- ? b↵
- 終了↵
テキストとして表示
- b=512↵
1秒 64M 0 テスト ケース 5 テキストとして表示
- a=10↵
- ? a↵
- b=-10+10↵
- ? b↵
- a=-10-10↵
- ? a↵
- c=a+-10+-10↵
- ? c↵
- d=-20+-8-8↵
- ? d↵
- e=a-12*-2↵
- ? e↵
- f=80--10+2↵
- ? f↵
- g=-10~-10↵
- ? g↵
- h=-10+-10↵
- ? h↵
- i=(90)↵
- ? 私↵
- k=(-100)↵
- ? k↵
- 終了↵
テキストとして表示
- a=10↵
- b=0↵
- a=-20↵
- c=-40↵
- d=-36↵
- e=4↵
- f=92↵
- g=0↵
- h=-20↵
- i=90↵
- k=-100↵
1秒 64M 0 テスト ケース 6 テキストとして表示
- abcdefgh=4↵
- 10=10↵
- a=18-32↵
- ? a↵
- b=18/abcdefgh↵
- ? b↵
- c=18%(b-1)↵
- ? c↵
- d=10+(10+10)*abcdefgh↵
- ? d↵
- e=10-2*10/abcdefgh↵
- ? e↵
- f=(18-3)*3↵
- ? f↵
- 十=十*(十)↵
- ? テン↵
- 十=十/10↵
- 10=(10+2)/(8-10)↵
- ? テン↵
- h=(2*3)/(5*2)↵
- ? h↵
- 10=10↵
- x=10-(80-30)/3*3+abcdefgh↵
- y=(((2+8)*2-(2+abcdefgh)/2)*2-8)*2↵
- z=(((8+2)*(abcdefgh/2)))↵
- ? ×↵
- ? y↵
- ? z↵
- 終了↵
テキストとして表示
- a=-14↵
- b=4↵
- c=0↵
- d=90↵
- e=5↵
- f=45↵
- 10=100↵
- 10=-6↵
- h=0↵
- x=-34↵
- y=52↵
- 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;
}