用逆波兰表达式的三角函数计算器

 
 
 
 
 
 
 
 
 
 
 
 
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<stack>
#include<iomanip>
#include"caltulator.h"
using namespace std;

typedef struct STK
{
	double num=889277;
	char note=0;
}stk;

char s[1000];//初始输入的数组
stk s1[1000];//字符串分割出来的部分
stk s3[1000];//最后的逆波兰表达式


bool if_minus(int & pos);
void turn_pi(int len);
double cut_num(int &pos)
{
	int f_pos = pos;      //一个数字的开始位置
	double integer = 0.0;
	double remainder = 0.0;
	int c = 0;
	while (s[pos] >= '0'&&s[pos] <= '9')
	{
		integer *= 10;
		integer += s[pos] - '0';
		pos++;
	}
	while (s[pos] == '.')
	{
		c = 1;
		pos++;
		while (s[pos] >= '0'&&s[pos] <= '9')
		{
			remainder += pow(0.1, c)*(s[pos]-'0');
			c++;
			pos++;
		}
	}
	//int pre_pos = f_pos - 1;     //一个数字开始之前的一个位
	
	return remainder + integer;
}

char cut_note(int &pos)
{
	if (s[pos] == '*')
	{
		pos++;
		return '*';
	}
	else if (s[pos] == '+')
	{
		pos++;
		return '+';
	}
	else if (s[pos] == '-')
	{
		pos++;
		return '-';
	}
	else if (s[pos] == '/')
	{
		pos++;
		return '/';
	}
	else if (s[pos] == '(')
	{
		pos++;
		return '(';
	}
	else if (s[pos] == ')')
	{
		pos++;
		return ')';
	}
	else if (s[pos] == 's')
	{
		pos++;
		if (s[pos] == 'i')
		{
			pos++;
			if (s[pos] == 'n')
			{
				pos++;
				return 's';
			}
			else return 0;
		}
		else return 0;
	}
	else if (s[pos] == 'c')
	{
		pos++;
		if (s[pos] == 'o')
		{
			pos++;
			if (s[pos] == 's')
			{
				pos++;
				return 'c';
			}
			else return 0;
		}
		else return 0;
	}
	else if (s[pos] == 'p')
	{
		pos++;
		if (s[pos] == 'i')
		{
			pos++;
			return 'p';
		}
		else
			return 0;
	}
	else if (s[pos] == 't')
	{
		pos++;
		if (s[pos] == 'a')
		{
			pos++;
			if (s[pos] == 'n')
			{
				pos++;
				return 't';
			}
			else return 0;
		}
		else return 0;
	}
	else return 0;
}

bool is_tf(char note)
{
	if (note == 'c' || note == 't' || note == 's')
		return 1;
	else
		return 0;
}

int cut_string()
{
	int len = strlen(s);
	int pos1 = 0;    //pos1是目标逆波兰表达式所对应的位置编号
	for (int pos = 0; pos < len;)
	{
		stk tmp;
		if (s[pos] == '#')
			exit(0);
		else if (s[pos] >= '0'&&s[pos] <= '9')
		{
			
			tmp.num = cut_num(pos);
		}
		else
		{ 
			char note = cut_note(pos);
			if (note)    //在判断步骤已经完成了一步自增,所以要把完成的一步自增减掉
			{ 
				if (note=='-')
				{
					if(if_minus(--pos))   //是负号
					{ 
						s1[pos1].num = 0;
						pos1++;

					}
					pos++;
					tmp.note = note;
				}
				else
				{
				  tmp.note = note;
				}
			}
			else
			{
				cout << "note error " <<pos<< endl;
				exit(0);
				return 0;
			}

		}
		//if (pos1 == 0&&tmp.num||tmp.note=='('||)
		s1[pos1] = tmp;
		pos1++;
	}
	return pos1;       //因为数组是从零开始计数,所以最后不用自减
}    //int 返回最后s1中有多少个结构体

int rate_class(char note)
{
	if (note == 'c' || note == 's' || note == 't')
		return 1;
	else
		return 2;
}

int rate_note(char n, int drct)
{

	if (n == '+' || n == '-')
	{
		return 1;
	}
	else if (n == '#')
		return -1;
	else if (n == '*' || n == '/')
		return 2;
	else if (n == '(' || n == ')')                                   //左右括号的级别都定为 0;
		return 0;
	else if ((n == 's' || n == 'c' || n == 't') && drct == 0)      //单目操作符的右级别为0;即在逆波兰表达式中的左结核性最低
		return 4;
	else if ((n == 's' || n == 'c' || n == 't') && drct == 1)      //左级别为3;即在逆波兰表达式中右结核性最高;
		return 3;
	else
	{
		cout << "error" << endl;
		exit(0);
	}
     
}

bool if_minus(int & pos)
{
	if (s[pos] != '-')
		return false;
	else {
		if (pos == 0 || (s[pos - 1] == 'n'&&s[pos - 2] == 'i'&&s[pos - 3] == 's') || (s[pos - 1] == 's'&&s[pos - 2] == 'o'&&s[pos - 3] == 'c') || (s[pos - 1] == 'n'&&s[pos - 2] == 'a'&&s[pos - 3] == 't') || s[pos - 1] == '(')
			return true;
		else return false;
	}
}

double operate_2(double a1, char op, double a2)
{
	switch (op)
	{
	case'+':return a1 + a2;
	case '-':return a1 - a2;
	case '*':return a1*a2;
	case '/':return a1 / a2;
	default:cout << "error"; return 0;
	}
}

double operate_1(double a, char op)
{
	switch (op)
	{
	case's':return sin(a);
	case'c':return cos(a);
	case't':
	{
		if (abs(cos(a))<0.00000001)
		{
			cout << "tan illegal  please reinput" <<endl;
			exit(0);
		}
		else 
	        return tan(a);
	}
	default: cout << "error"; exit(0);
	}
}

int mtor()
{
	int len = cut_string();
	turn_pi(len);
	stack<stk> s2;
	stk tmp;
	tmp.note = '#';
	s2.push(tmp);
	int pos3= 0;
	for (int pos1 = 0;pos1 < len; pos1++)
	{
		if (!s1[pos1].note)             //这个位置是数字的情况,note为空
		{
			s3[pos3] = s1[pos1];
			pos3++;
		}
		else
		{
			if (s1[pos1].note == '(')
			{
				stk tmp;
				tmp.note = '(';
				s2.push(tmp);
			}
			else if (s1[pos1].note == ')')
			{
				int flag = 1;         //是否到了(,sin,cos的需要终结的部分
				while ((s2.top().note!='#')&&(flag||rate_note(s2.top().note, 1)==0|| rate_note(s2.top().note, 1) == 3))//flag为1或者是top的符号为0的时候可以继续往下做
				{
					if (flag&&s2.top().note == '(')
					{
						flag = 0;
						s2.pop();
					}
					else
					{ 
					stk tmp;
					tmp = s2.top();
					s3[pos3] = tmp;
					pos3++;
					s2.pop();
					}
				}
			}
			else if ((s2.top().note != '#')&&rate_note(s1[pos1].note, 0) <= rate_note(s2.top().note, 1))           //需要进栈的note的左优先级要大于在栈中的右优先级时,可以进栈
			{
				while (rate_note(s1[pos1].note, 0) <= rate_note(s2.top().note, 1))
				{
					stk tmp = s2.top();
					s2.pop();
					s3[pos3] = tmp;
					pos3++;
				}
				s2.push(s1[pos1]);
			}
			else
			{
				s2.push(s1[pos1]);
			}
		}
	}
	while ((s2.top().note != '#'))
	{
		stk tmp;
		tmp = s2.top();
		s2.pop();
		s3[pos3] = tmp;
		pos3++;
	}
	
	return pos3;
}

void turn_pi(int len)
{
	for (int pos = 0; pos < len; pos++)
	{
		if (s1[pos].note == 'p')
		{
			s1[pos].note = 0;
			s1[pos].num = 3.1415926;
		}
	}
}

double compute()
{
	int len = mtor();

	stack<double>s4;
	for (int pos3 = 0; pos3 < len; pos3++)
	{
		if (s3[pos3].note)                          //当是操作符的时候
		{
			if (rate_class(s3[pos3].note) == 1)    //单目操作符
			{
				double tmp=s4.top();
				s4.pop();
				tmp=operate_1(tmp, s3[pos3].note);
				s4.push(tmp);
			}
			else
			{
				double tmp1 = s4.top();
				s4.pop();
				double tmp2 = s4.top();
				s4.pop();
				double tmp = operate_2(tmp2, s3[pos3].note, tmp1);
				s4.push(tmp);
			}


		}
		else
		{
			s4.push(s3[pos3].num);
		}
	}
	return s4.top();
}

/*bool is_legal(int len)
{
	for (int pos1 = 0; pos < len; pos++)
	{
		if (pos1 == 0)
			if ((s1[pos1] == 's' || s1[pos1] == 'c' || s1[pos1] == 't' || if_mins(pos1))
				;
			else
			{
				cout << "note error" << pos1 << endl;
				exit(0);
			}
		else if (pos1 < len - 1)
		{
			if (s1[pos1] == '*' || s1[pos1] == '-' || s1[pos1] == '/' || s1[pos1] == '+')
			{
				pos_r = pos + 1;
				if (s1[pos_r] == ')' || s1[pos_r] == '+' || s1[pos_r] == '*' || s1[pos_r] == '-' || s1[pos_r] == '/')
				{
					cout << "note error" << pos1 << endl;
					exit(0);
				}

			}
			else if(s1[pos1]==)
		}
	}
}
*/
int main()
{
	cout << "请输入一个合法的表达式(请给所有的负数都加括号)" << endl;
	cout << "如果要退出请输入 ‘#’ " << endl;
	cin >> s;
	while (s[0] != '#')
	{
		//if (is_legal)
		if(1)
		{
			double result;
			result = compute();
			cout << "这个表达式的计算结果为: "<< fixed << setprecision(8)<< result<<endl;
			cout << "请输入一个合法的表达式(请给所有的负数都加括号)" << endl;
			cout << "如果要退出请输入 ‘#’ " << endl;
		}
		else
		{
			cout << "请输入一个合法的表达式" << endl;
			cout << "如果要退出请输入 ‘#’ " << endl;
		}
		cin >> s;
	}


}//愁死我了,不会用这个编辑器,以上代码还没有写完,但是把字符串正确性检测注释掉,是可以跑的,假期填坑。这个代码太菜了,菜到自己没眼看。

猜你喜欢

转载自blog.csdn.net/qq_36403658/article/details/72954012