题目链接: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;
}