题意:
计算数学表达式的值,
数学表达式的定义: 4个[0-9]表示数字的字符 ,3个[+-x/]表示运算的字符
可以用正则为: ([0-9][+-x/]){3}[0-9]
例如: 5+2/1x3
2-1+7x3
3x3/3x3
找到图片了,不啰嗦了...
这道题只有7个字符,数字只有一位不算太难
先算乘除,后算加减,考试的时候就是这样做的,用stack完美解决
但如果加大难度....
1) 数字允许有多位比如 1314-521*233
2) 再比如如果有括号呢 -1-(1-(-9))
让我们按照函数化的思想逐渐完善我们的代码
(1) 7个字符版本
1 #include <iostream> 2 #include <algorithm> 3 #include <stack> 4 using namespace std; 5 int get_ans (string str) { 6 stack <int> s; 7 int flag=1; 8 for (int i=0;i<str.size();i++) { 9 if (str[i]>='0'&&str[i]<='9') s.push( flag*(str[i]-'0')); 10 else if (str[i]=='-' || str[i]=='+') { 11 if (str[i]=='-') flag=-1; 12 else flag=1; 13 } 14 else { 15 int x1=s.top(); s.pop(); 16 i++; // importment !! 17 int x2=str[i]-'0'; 18 if (str[i-1]=='/') s.push(x1/x2); 19 else s.push(x1*x2); 20 } 21 } 22 int sum=0; 23 while (!s.empty()) { 24 sum+=s.top(); 25 s.pop(); 26 } 27 return sum; 28 } 29 int main () 30 { 31 int T; cin>>T; 32 while (T--) { 33 string str; cin>>str; 34 cout<<get_ans(str)<<endl; 35 } 36 return 0; 37 }
2 允许有连续的输入数字: 233*521
我们加入一个输入接口get_num: 如果下一个字符是数字,就一直读下去
1 #include <iostream> 2 #include <algorithm> 3 #include <stack> 4 using namespace std; 5 6 int get_num(string str,int &k) { 7 // 从k开始一直读所有的数字字符 8 int ans=0; 9 for (;k<str.size();k++) { 10 if (str[k]>='0' && str[k]<='9') 11 ans=ans*10+str[k]-'0'; 12 else break; 13 } 14 k--; // i 此时指向最后一个数字的位置 15 return ans; 16 } 17 18 int get_ans (string str) { 19 stack <int> s; 20 int flag=1; 21 for (int i=0;i<str.size();i++) { 22 if (str[i]>='0'&&str[i]<='9') { 23 int num=get_num(str,i); 24 s.push(flag*num); 25 } 26 else if (str[i]=='-' || str[i]=='+') { 27 if (str[i]=='-') flag=-1; 28 else flag=1; 29 } 30 else { 31 char ch=str[i]; 32 int x1=s.top(); s.pop(); 33 i++; 34 int x2=get_num(str,i); 35 if (ch=='/') s.push(x1/x2); 36 else s.push(x1*x2); 37 } 38 } 39 int sum=0; 40 while (!s.empty()) { 41 sum+=s.top(); 42 s.pop(); 43 } 44 return sum; 45 } 46 47 int main () 48 { 49 int T; cin>>T; 50 while (T--) { 51 string str; cin>>str; 52 cout<<get_ans(str)<<endl; 53 } 54 return 0; 55 }
3 最难的部分,遇到括号怎么办---
我们也只需要加一个接口
其核心就是把一对括号里面的字符,放入我们之前的接口算出结果,从而达到去除括号的效果
例子: 1*(3-(5-4)) ->1*(3-1)->1*2>2
总之就是把一个问题切分成一个一个小问题
1 #include <iostream> 2 #include <algorithm> 3 #include <stack> 4 using namespace std; 5 string to_str (int x) { 6 if (x==0) return "0"; 7 string ans; 8 bool flag=0; 9 if (x<0) { 10 flag=1; 11 x=-x; 12 } 13 while (x) { 14 ans+=x%10+'0'; 15 x/=10; 16 } 17 if (flag) ans+='-'; 18 return ans; 19 } 20 21 int get_num(string str,int &k) { 22 int ans=0; 23 for (;k<str.size();k++) { 24 if (str[k]>='0' && str[k]<='9') 25 ans=ans*10+str[k]-'0'; 26 else break; 27 } 28 k--; // i 此时指向最后一个数字的位置 29 return ans; 30 } 31 32 int get_no_ans (string str) { 33 stack <int> s; 34 int flag=1; 35 for (int i=0;i<str.size();i++) { 36 if (str[i]>='0'&&str[i]<='9') { 37 int num=get_num(str,i); 38 s.push(flag*num); 39 } 40 else if (str[i]=='-' || str[i]=='+') { 41 if (str[i]=='-') { 42 if (i-1&&str[i-1]=='-') flag=-flag; 43 else flag=-1; 44 } 45 else flag=1; 46 } 47 else { 48 char ch=str[i]; 49 int x1=s.top(); s.pop(); 50 i++; 51 int x2=get_num(str,i); 52 if (ch=='/') s.push(x1/x2); 53 else s.push(x1*x2); 54 } 55 } 56 int sum=0; 57 while (!s.empty()) { 58 sum+=s.top(); 59 s.pop(); 60 } 61 return sum; 62 } 63 64 int get_ans (string str) { 65 str="("+str+")"; 66 stack <char> s; 67 int ans; 68 for (int i=0;i<str.size();i++) { 69 if (str[i]==')') { 70 string tmp; 71 while (s.top()!='(') { 72 tmp+=s.top(); 73 s.pop(); 74 } 75 s.pop(); 76 reverse(tmp.begin(), tmp.end()); 77 int num=get_no_ans(tmp); 78 //cout<<tmp<<"@@@"<<num<<endl; 79 tmp=to_str(num); 80 for (int j=tmp.size()-1;j>=0;j--) s.push(tmp[j]); 81 if (i==str.size()-1) ans=num; 82 } 83 else s.push(str[i]); 84 } 85 return ans; 86 } 87 88 int main () 89 { 90 int T; cin>>T; 91 while (T--) { 92 string str; cin>>str; 93 cout<<get_ans(str)<<endl; 94 } 95 return 0; 96 }
抓住青春的尾巴。。。