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