2019网易实习笔试题——给字符串定义符号运算(上)
下面的代码参考了这位大神的:吾落凡
//判断是否为括号
bool isPra(string c) //为了统一,采用字符串操作
{
if (c == "(" || c == ")")
return true;
else
return false;
}
//获得符号的优先性
int getPri(char c)
{
switch (c) //返回值代表不同的优先级
{
case '+':
case '-':
return 0; //如果是加减,返回0
break;
case '*':
case '/':
return 1; //如果是乘除,返回1
break;
case '!': //如果是逆置或者 大写变小写,返回2
case '~':
return 2;
break;
case '(':
case ')':
return -1; //注意,这里将括号设为最低优先级,因此括号不会被弹出,除非遇到右括号
break;
}
}
//判断符号的优先性
void check(string c, stack<string> &coll2, deque<string> &string_suffix)
{
if (coll2.empty())
{
coll2.push(c);
return;
}
if (isPra(c))
{
if (c == "(")
coll2.push(c);
else
{
//弹出所有元素直到遇到左括号
while (coll2.top() != "(")
{
string ch = coll2.top();
string_suffix.push_back(ch);
coll2.pop();
}
//当遇到左括号时,弹出但不加入coll3(后缀表达式中)
coll2.pop();
}
}
else //如果不是括号
{
//取出栈顶元素,与当前符号进行优先性比较
string sym = coll2.top();
char c_temp = c[0]; //因为字符串的长度只为 1,所以采用这种方法将字符串转化为字符,用于后续比较操作符的优先级
char sym_temp = sym[0];
//比较两符号的优先性
if (getPri(c_temp) <= getPri(sym_temp))
{
//如果c的优先性比栈顶符号小或等于,弹出栈顶元素
coll2.pop();
//并将其压入string_suffix(后缀表达式)中
string_suffix.push_back(sym);
//递归调用check,比较当前符号c与下一个栈顶符号的优先性
check(c, coll2, string_suffix);
}
else
{
//如果c比栈顶符号优先级大,那将c压入coll2(操作符栈)中
coll2.push(c);
}
}
}
//从coll中取出元素,分配元素到coll2和coll3中
void allocate(deque<string> &s_string, stack<string> &coll2, deque<string> &string_suffix) //生成后缀表达式
{
while (!s_string.empty())
{
string c = s_string.front();
s_string.pop_front();
if (c.size()!=1)
{
string_suffix.push_back(c);
}
else
{
//调用check函数,针对不同情况作出不同操作
check(c, coll2, string_suffix);
}
}
//如果输入结束,将coll2的元素全部弹出,加入后缀表达式中
while (!coll2.empty())
{
string c = coll2.top();
string_suffix.push_back(c);
coll2.pop();
}
}
//计算后缀表达式
void calculate(deque<string> &string_suffix, stack<string> &string_result) // string_suffix 存放的是后缀表达式 string_result 是存放计算结果的
{
while (!string_suffix.empty())
{
string c = string_suffix.front();
string_suffix.pop_front();
//如果是操作数,压入栈中
if (c.size() != 1)
{
string_result.push(c);
}
else //如果是操作符,从栈中弹出元素进行计算
{
char c_temp = c[0];
string op1 = string_result.top();
string_result.pop();
if (c_temp == '!' || c_temp == '~') //一元操作符
{
if (c_temp == '!')
{
string_reverse(op1);
string_result.push(op1);
}
else
{
string_tochange(op1);
string_result.push(op1);
}
}
else //二元操作符
{
string op2 = string_result.top();
string_result.pop();
switch (c_temp) //根据运算符调用不同的函数
{
case '+':
string_add(op2, op1); //在计算后缀表达式的时候,如果对两个数的顺序有要求的话,一定要按照输入的顺序进行操作,那么后取出来的数是在前面的
string_result.push(op2);
break;
case '-':
string_minus(op2, op1);
string_result.push(op2);
break;
case '*':
string_multiplication(op2, op1);
string_result.push(op2);
break;
case '/':
string_division(op2, op1);
string_result.push(op2);
break;
//case '!':
// string_result.push(op2); //一元操作符,所以需要把第二个元素压入栈中,后来发现这个错误的,当你的一元操作符在最前面的是,此时的 string_result 中只有一个元素,在进行弹出第二个元素的时候,会报错
// string_reverse(op1);
// string_result.push(op1);
// break;
//case '~':
// string_result.push(op2);
// string_tochange(op1);
// string_result.push(op1);
// break;
}
}
}
}
}
主函数
int main()
{
deque<string> s_string; //盛放中缀表达式
stack<string> coll2;
deque<string> string_suffix; //盛放后缀表达式
stack<string> string_result; //计算后缀表达式的辅助容器
string s;
cin >> s;
for (int i = 0; i < s.size();)
{
string temp;
while (s[i] >= 'A' && s[i] <= 'Z' || s[i] >= 'a' && s[i] <= 'z') //如果s[i] 是字母
temp = temp + s[i++];
if (!temp.empty())
s_string.push_back(temp);
else
{
temp = s[i++];
s_string.push_back(temp);
}
}
allocate(s_string, coll2, string_suffix); //从s_string中取出元素,得到后缀表达式 string_suffix 中
calculate(string_suffix, string_result); //计算后缀表达式
cout << string_result.top() << endl;
system("pause");
return 0;
}
计算结果
(ABC+EDF*jhi)/ABC-jhi ——》 EDjhiF
(!WER+~TY+ABC+EDF*jhi)/ABC-jhi ——》 REWtyEDjhiF