本文用stack实现了一个计算器,支持括号、小数、负数。代码比较简单,没加什么注释。实际使用时,读取用户在stdin的输入,而后计算。若格式错误,会抛出异常。git
在实际计算过程当中,实际分为三步:github
本代码有对应的bin/calc.dart 入口,而且使用了最新版的stack实现。后续文章会贴出来。或者能够到个人github上看:spa
https://github.com/Buerkut/data_structcode
代码以下:orm
1 import 'package:data_struct/stack/stack.dart'; 2 3 num calc(String ins) { 4 try { 5 var es = _preCalc(_eliminateSpace(ins)); 6 return _calc(es); 7 } catch (e) { 8 throw FormatException(); 9 } 10 } 11 12 String _eliminateSpace(String ins) => ins.replaceAll(RegExp(r'\s+'), ''); 13 14 Stack<String> _preCalc(String ins) { 15 var es = Stack<String>(); 16 for (var i = ins.length - 1; i >= 0; i--) { 17 if (_isDigit(ins[i])) { 18 var j = i--; 19 while (i >= 0 && _isDigit(ins[i])) i--; 20 if (ins[i] == '-' && (i == 0 || ins[i - 1] == '(')) { 21 es.push(ins.substring(i, j + 1)); 22 } else { 23 es.push(ins.substring(++i, j + 1)); 24 } 25 } else if (ins[i] == '(') { 26 var a = _calc(es); 27 es 28 ..pop() 29 ..push(a.toString()); 30 } else { 31 es.push(ins[i]); 32 } 33 } 34 return es; 35 } 36 37 num _calc(Stack<String> es) { 38 num a = _d(es.pop()); 39 while (es.isNotEmpty && es.top != ')') { 40 var op = es.pop(); 41 var b = _d(es.pop()); 42 if ((op == '+' || op == '-') && 43 es.isNotEmpty && 44 (es.top == '*' || es.top == '/')) { 45 while (es.isNotEmpty && (es.top == '*' || es.top == '/')) { 46 var prop = es.pop(); 47 var c = _d(es.pop()); 48 b = prop == '*' ? b * c : b / c; 49 } 50 } 51 switch (op) { 52 case '+': 53 a += b; 54 break; 55 case '-': 56 a -= b; 57 break; 58 case '*': 59 a *= b; 60 break; 61 case '/': 62 a /= b; 63 break; 64 default: 65 break; 66 } 67 } 68 return a; 69 } 70 71 num _d(String s) => num.parse(s); 72 73 bool _isDigit(String c) => 74 (c.codeUnitAt(0) >= 48 && c.codeUnitAt(0) <= 57) || c.codeUnitAt(0) == 46;