题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1014
这几天因为做题做烦了,但有不想浪费时间,所以就直接抄的代码,但是收获还是有的。
首先是关于几个函数的用法:
1.cin.ignore():函数可以给参数也可以不给参数。若给参数,可以是一个整数,表示忽略输入流中的指定个数的字符,也可以是一个字符,表示忽略指定的字符,也可以同时给整型和字符型参数,整型在前,字符在后,表示忽略指定个数或指定字符,满足其中之一函数就会停止;
2.cin.peek():返回输入流中当前流的下一个字符,说白了,就是即将要读取到的字符;
3.string中的substr():两个参数s.substr(pos,length),表示返回s中从s[pos]开始的长度为length的字符串。
接下来就是提取表达式了。乍一看题,以为表达式的名字不一定会是一个字符,有可能会是多个字符,在向后看题,感觉会用到递归可能会特别麻烦,然后就懒得想了,于是看了题解,才发现不用递归。
关于对括号的处理,可以先越过括号,因为括号的优先级最高,一定是最后提取的,所以可以先忽略,但一定要保证成对。
对于括号任然有一个疑问什么情况下应该去掉括号,什么情况下不应该去掉括号,在给出的两个样例中的括号的去留没哟任何道理,这也是我不想做这道题的原因之一。题解的代码只是处理了一层括号,如果同时有多层括号就会出现让人难以接受的结果,比如对((x))提取第一个表达式,结果应该是x但是得到的结果却是(x),让人难以理解。
#include<iostream> #include<list> #include<sstream> #include<cstdio> using namespace std; char optSign[3] = {'+', '*', '^'}; string Operand(int n, string s) { int Count; int bracket; bool found; string answer = ""; for (int i=0; i<3; i++) { Count = 1; bracket = 0; found = false; answer = ""; for (int j=0; j<s.length(); j++) { answer += s[j]; if (s[j] == '(') { bracket++; continue; } else if (s[j] == ')') { bracket--; continue; } else if (bracket) continue; else if (s[j] != optSign[i]) continue; else { if (Count == n) return answer.substr(0,answer.length() - 1); else { found = true; answer = ""; Count++; } } } if (found) return answer; } if (s[0] == '(') return s.substr(1,s.length() - 2); else return s; } int main() { int Count; string src; char ename; bool lineFlag = true; list<int> question; while (cin>>src && src!="*") { if (lineFlag) lineFlag = false; else cout<<endl; ename = src[0]; src = src.substr(3); cout<<"Expression "<<ename<<":"<<endl; cin>>Count; cin.ignore(); while (Count--) { int n; string ops = src; question.clear(); while (cin.peek() != '\n') { cin>>n; question.push_back(n); ops = Operand(n,ops); } cin.ignore(); int bkc = question.size(); while (!question.empty()) { int n = question.back(); question.pop_back(); cout<<"op("<<n<<","; } cout<<ename; for (int i=1; i<=bkc; i++) cout<<")"; cout<<"="<<ops<<endl; } } return 0; }