本文用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;