给你一个表达式,首先判断是不是合法的C表达式,然后在这个题中,所有运算符没有优先级,只依靠括号决定运算顺序,所以挖掘出一个隐含的结论(划重点):有n个运算符的话,必须有n - 1对合法的括号(自然地每对括号里只有一个运算符和两个运算数)。判断时使用栈,然后就是考虑不符合正确C表达式的所有情况分类讨论就好。
注意:一个大bug就是,读入的表达式之间有空格,不能用scanf读入zi'fu'c
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn = 1010;
char str[maxn];
int id[maxn];
bool check() //判断合法C表达式的函数
{
int len = strlen(str);
if(len == 1 && id[0] == 1) return true;
for(int i = 0; i < len; i++)
{
if(isalpha(str[i]))
id[i] = 0;
else if(str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' || str[i] == '%')
{
id[i] = 1;
}
else if(str[i] == '(') //(b+(a+c))+b 20120103310
id[i] = 2;
else
id[i] = 3;
}
if(id[0] == 1 || id[len - 1] == 1) {return false;}
if(id[0] == 3 || id[len - 1] == 2) {return false;}
for(int i = 1; i < len; i++)
{
if(id[i - 1] == 0 && id[i] == 0) {return false;} //aa
else if(id[i - 1] == 0 && id[i] == 2) {return false;} //a(
else if(id[i - 1] == 1 && id[i] == 1) {return false;} //++
else if(id[i - 1] == 1 && id[i] == 3) {return false;} //+)
else if(id[i - 1] == 2 && id[i] == 1) {return false;} //(+
else if(id[i - 1] == 2 && id[i] == 3) {return false;} //()
else if(id[i - 1] == 3 && id[i] == 0) {return false;} //)a
else if(id[i - 1] == 3 && id[i] == 2) {return false;} //)(
}
int cnt = 0;
for(int i = 0; i < len; i++)
{
if(id[i] == 2) cnt++;
else if(id[i] == 3)
{
if(!cnt) return false;
else cnt--;
}
}
return cnt == 0;
}
bool judge() //判断
{
stack<char> st;
int sym = 0;
int pnum = 0;
int len = strlen(str);
if(len == 1 && id[0] == 0) return true;
for(int i = 0; i < len; i++)
{
if(id[i] == 0) continue;
if(id[i] == 1)
{
st.push(str[i]); sym++;
}
else if(id[i] == 2)
{
st.push('(');
}
else if(id[i] == 3)
{
int inner = 0;
while(!st.empty())
{
//别先单独写一个st.top放在循环外同时while(st.top()!='(',因为正确表达式一对括号中就一个运算符,这样导致进入后即退出,inner一直为0,隐形bug...
char ch = st.top();
st.pop();
if(ch == '(') break;
else inner++;
}
if(inner != 1) return false; //只能为1
else pnum++; //括号对数
}
}
return pnum == sym - 1; //括号对数是否等于运算符数-1
}
int main()
{
//scanf("%s", str); WA point!!!
gets(str);
int tot = 0;
int len = strlen(str);
for(int i = 0; i < len; i++)
{
if(str[i] != ' ')
str[tot++] = str[i];
}
str[tot] = 0;
bool formal = check();
if(formal)
{
bool ok = judge();
if(ok) cout << "proper" << endl;
else cout << "improper" << endl;
}
else
cout << "error" << endl;
return 0;
}