哈工大2022数据结构实验一 算术计算器

鉴于以前在CSDN也获得了前辈们的许多帮助,这里也发布一篇实验的代码文章

实验项目1:栈结构及其应用

实验题目:算术表达式求值(算术计算器)

实验内容:

表达式求值是实现程序设计语言的基本问题之一,也是栈的应用的一个典型例子。一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。假设操作数是正整数,运算符只含加减乘除等四种二元运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。引入表达式起始、结束符是为了方便。设计一个程序,演示算术表达式求值的过程。

实验要求:

  1. 从文本文件输入任意一个语法正确的(中缀)表达式,显示并保存该表达式。
  2. 利用栈结构,把(中缀)表达式转换成后缀表达式,并以适当的方式展示栈的状态变化过程和所得到的后缀表达式。
  3. 利用栈结构,对后缀表达式进行求值,并以适当的方式展示栈的状态变化过程和最终结果。

运行结果截图:

 

 

注:程序中运用了to_string函数,所以需要在c++11及以上环境中运行

#include <iostream>
#include <cstring>
#include <cstdlib>

using namespace std;

struct node {
	string data;
	node* next;
};

typedef node* STACK;

void Getstr_done(char str[], char str_done[]);
bool Check(char str[]);
int pri(char op);
STACK MakeNull();
string Tostring(char x);
void Pop(STACK S);
void Push(string x, STACK S);
string Top(STACK S);
void PrintSTACK(STACK S);
void Print(string b);
bool IsEmpty(STACK S);
string GetArith(char a[], string b, STACK S);
void Colc(string Arith, STACK S);
int IsMulti(char str[], int x);

int main(){
	cout << "1.以#开头和结束"<<endl;
	cout << "2.表达式中不含其他字符"<<endl;
	cout << "3.只进行正整数(int)间的运算"<<endl;
	cout << "----------------------" <<endl;
	cout << "请输入中缀表达式:" <<endl;
	char str[200];								//储存最初的中缀表达式(包含#) 
	cin >> str;
	char str_done[strlen(str)-2];				//储存开始符与结束符中的中缀表达式
	string Arith;								//储存生成的后缀表达式
	if (Check(str) == 0){
		cout << "输入错误!" <<endl;
		return 0;
	}
	else {
		Getstr_done(str, str_done); 
		STACK S;
		S = MakeNull();
		Arith = GetArith(str_done, Arith, S);
		cout << "得到后缀表达式:"<<endl; 
		cout<<Arith<<endl;
		S = MakeNull();
		cout << "开始计算后缀表达式:"<<endl;
		Colc(Arith, S);
		return 0;
	} 
}

void Getstr_done(char str[], char str_done[]){		//取得开始符与结束符中的中缀表达式
	for (int i=0; i<strlen(str)-1; i++){
		str_done[i] = str[i+1];
	}
	str_done[strlen(str)-2] = '\0';					//结尾加上结束符 
	cout << "提取中缀表达式:" <<endl;
	cout << str_done <<endl;
	cout << "----------------------" <<endl;
}

bool Check(char str[]){									//检查表达式输入合法性 
	if (str[0] != '#' || str[strlen(str)-1] != '#') return false;
	for (int i=0; i<strlen(str); i++){
		if (!((str[i]>=48 && str[i]<=57) || (str[i]!='(') || (str[i]!=')') || (str[i]!='+') || (str[i]!='-') || (str[i]!='*') || (str[i]!='/')))
		return false;
	}
	return true;
} 

string GetArith(char str_done[],string Arith, STACK S){				//中缀转后缀,后缀存为string 
	for (int i=0; i<strlen(str_done); i++){	
		if (pri(str_done[i]) == 3){									//数字情况
			if (IsMulti(str_done, i)){							//若某位字符是多位数中间的数字,则后缀表达式不加空格 
				Arith += str_done[i];		
				PrintSTACK(S);
				Print(Arith);
			}								 
			else{
				Arith += str_done[i]; 
				Arith += " ";
				PrintSTACK(S);
				Print(Arith);
			}	
		}
		else //非数字情况 
        {
            //栈空直接入栈 
            if(IsEmpty(S) == 1){
            	Push(Tostring(str_done[i]), S);
            	PrintSTACK(S);
				Print(Arith);
			}
            //左括号直接入栈 
            else if(str_done[i] == '('){
            	Push(Tostring(str_done[i]), S);
            	PrintSTACK(S);
				Print(Arith);
			}
            //右括号按要求弹出 
            else if(str_done[i] == ')')
            {
                while(Top(S)[0] != '(')
                {
                    Arith += Top(S)[0];
                    Arith += " ";
                    Pop(S);
                }
                //弹出左括号,但不输出 
                Pop(S);
                PrintSTACK(S);
				Print(Arith);
            }
            else{
                //优先级弹出 
                while(pri(str_done[i]) <= pri(Top(S)[0])){			//Top(S)[0]指字符串中的首元素 
                    Arith += Top(S)[0];
                    Arith += " ";
                    Pop(S);
                    //栈空停止 
                    if(IsEmpty(S) == 1) break;
                }
                Push(Tostring(str_done[i]), S);
            }
        }
        cout << "----------------------" <<endl;
	}
	while (IsEmpty(S) != 1){				//最终清空栈内运算符 
		Arith += Top(S)[0];
		Arith += " ";
		Pop(S);
		PrintSTACK(S);
		Print(Arith);
		cout << "----------------------" <<endl; 
	}
	return Arith;
}

void Colc(string Arith, STACK S){		//由后缀表达式计算结果 
	for (int i=0; i<Arith.length(); i++){
		if (pri(Arith[i]) == 3){
			string tmp;					//将数字以字符串形式存在栈中 
			for (int j=i; j<Arith.length(); j++){
				tmp += Arith[j];
				if (pri(Arith[j+1]) == 3) continue; 		//多位数数字持续读取到末尾 
				else{
					Push(tmp, S);		//数字入栈 
					i = j+1;
					break;
				}
			}
			PrintSTACK(S);
		}
		if (Arith[i] == ' ') continue;		//空格直接跳过 
		else if (Arith[i] == '+'){
			float a = atof(Top(S).c_str());
			Pop(S);
			float b = atof(Top(S).c_str());
			Pop(S);
			float c = (float)b+(float)a;
			Push(to_string(c), S);
			PrintSTACK(S);
		}
		else if (Arith[i] == '-'){
			float a = atof(Top(S).c_str());
			Pop(S);
			float b = atof(Top(S).c_str());
			Pop(S);
			float c = (float)b-(float)a;
			Push(to_string(c), S);
			PrintSTACK(S);
		}
		else if (Arith[i] == '*'){
			float a = atof(Top(S).c_str());
			Pop(S);
			float b = atof(Top(S).c_str());
			Pop(S);
			float c = (float)b*(float)a;
			Push(to_string(c), S);
			PrintSTACK(S);
		}
		else if (Arith[i] == '/'){
			float a = atof(Top(S).c_str());
			Pop(S);
			float b = atof(Top(S).c_str());
			Pop(S);
			float c = (float)b/(float)a;
			Push(to_string(c), S);
			PrintSTACK(S);
		}
	}
	cout << "最终结果:" << Top(S) <<endl;
}

int pri(char op){				//符号优先级 
    int pri;
    if(op >= 48 && op <= 57) pri = 3;
    if(op == '*' || op == '/') pri = 2;
    if(op == '+' || op == '-') pri = 1;
    if(op == '(') pri = 0;
    if(op ==')' || op == '#') pri = 4;		//此处将两者定义防止出bug 
    return pri;
}

STACK MakeNull(){
	STACK S = new node;
	S->next = NULL;
	return S;
}

void Pop(STACK S){
	STACK stk;
	if (S->next){	
		stk = S->next;
		S->next = stk->next;
		delete stk;
	}
}

void Push(string x, STACK S){	
	STACK stk;
	stk = new node;
	stk->data = x;
	stk->next = S->next;
	S->next = stk;
}

void PrintSTACK(STACK S){
	node* L = S -> next;
	cout << "栈:" <<endl; 
	while (L!=NULL){
		cout << L->data << " ";
		L = L->next;
	}
	cout <<endl;
}

string Top(STACK S){				//返回栈顶元素的data值 
	if (S->next != NULL){
		return S->next->data;
	}
	else return 0;	
}

void Print(string Arith){
	cout << "后缀表达式: ";
	cout << Arith <<endl;
}

bool IsEmpty(STACK S){	
	if (S->next == NULL) return true;
	else return false;
}

string Tostring(char x){		//将char转换为string,便于后缀表达式的多位数计算 
    string s;
    s.append(1, x);
    return s;
}

int IsMulti(char str[], int x){		//判断多位数,若为多位数的中间数字,则输出1,代表不加空格。否则输出0,代表加空格 
	if (pri(str[x]) == 3 && x == strlen(str)-1) return 0;		//若表达式最后一个字符是数字,则输出0,在此数字后加空格 
	if (pri(str[x]) != 3) return 0;			//若不是数字,直接加空格 
	else if (pri(str[x]) == 3 && pri(str[x+1]) == 3) return 1;			//是多位数中间的数字,输出1,不加空格 
	return 0;
} 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值