任务:后缀计算器
write a postfix expression evaluator. An expression consists of operands and operators. An operand is a signed integer (isize
). An operator is +
, -
, or *
with their common semantics. An expression is valid if it can be evaluated to a signed integer.
For example, the following are valid expressions:
-100
1 2 +
1 2 3 + *
The following expressions are invalid:
// empty expression
-1 -2
1 2 + *
一个入门级的问题,考验对array的操作、自定义类型、函数的应用和控制流。
思路为类栈操作,遍历输入的表达式,遇到数字就压栈,遇到操作符就将栈顶层的两个元素推出操作,最后打印栈。
注意三种情况:对一个操作符栈中没有两个操作数、遍历完成栈中有不止一个数字、表达式为空值。
废话少说,上代码
pub enum Operator {
// `+`
Add,
// `-`
Sub,
// `*`
Mul,
}
pub enum Token {
Operator(Operator),
Operand(isize),
}
/// Evaluates the postix expression.
///
/// Input: a postfix expression, where each element contains an operator or operand.
/// Returns: if the postfix expression is valid, returns `Some(value)`;
/// otherwise, returns `None`.
pub fn eval(tokens: & [Token]) -> Option<isize> { //tokens is a &[Token]. and it is inmutable.
let mut stack=Vec::new(); //create an empty vector called stack.
if tokens.len()==0{
return None //return a value, familiar with Python.
}
else{
for i in tokens{ //warning: &[Token] has no attribuate len(), so I can only use for method
match i{ // warning: i is &[Token], and branches should be also &[Token]
&Token::Operand(isize) => {
stack.push(isize);
}
&Token::Operator(ref operator)=> { //I'm sure the meaning of ref
match operator{
&Operator::Add => {if stack.len()>1{ //I can do many operations behind match, such as implement expressions, implement macros(println!,...), assigning a value
let operand1 =stack.pop().unwrap(); //so do ref
let operand2 =stack.pop().unwrap();
let result = operand1 + operand2;
stack.push(result);}
else{return None}
}
&Operator::Sub => {if stack.len()>1{
let operand1 =stack.pop().unwrap();
let operand2 =stack.pop().unwrap();
let result = operand2 - operand1;
stack.push(result);}
else{return None}
}
&Operator::Mul => {if stack.len()>1{
let operand1 =stack.pop().unwrap();
let operand2 =stack.pop().unwrap();
let result = operand1 * operand2;
stack.push(result);}
else{return None}
}
}
}
}
}
}
if stack.len() == 1{
let jg = stack.pop().unwrap();
Some(jg) //return should be an option, so Some() an isize
}
else{
return None
}
}
缺少main函数,尝试编译会报error
接下来定义main()调用eval函数:
fn main(){
let x = eval(&[Token::Operand(3),
Token::Operand(2),
Token::Operand(5),
Token::Operator(Operator::Sub),
Token::Operand(6),
Token::Operator(Operator::Mul),
Token::Operator(Operator::Add)]);
println!("{}{:?}", "Your result is :",x);
}
运行结果为-15
计算器功能尚不完善,以后再完善
值得注意的是这里输入类型为一个Token类型的array拷贝,代码没有更改的权限。关于Rust所有权与借用,以后会详细解析。