【问题标题】:A Reverse Polish Notation Calculator in Angular.jsAngular.js 中的逆波兰符号计算器
【发布时间】:2017-06-10 23:16:16
【问题描述】:

我正在尝试在 Angular.js 中实现一个简单的逆波兰表示法计算器,到目前为止,该代码可以处理一位数的计算,例如

2 3 +

如何修改它以处理多于一位的输入,例如:

122 233 +

这是我参加这个discussion后想到的一个想法)。我怀疑我可能不得不使用 onkeypressparseInt 和/或 parseFloat 但我不确定。我期待着你的想法。谢谢。

JavaScript:

var calcApp = angular.module('calcApp', []);

calcApp.controller('calcCtrl', function ($scope) {

    $scope.leftOperand = "";
    $scope.operator = "";
    $scope.rightOperand = "";
    $scope.answer = "";


    $scope.setOperand = function (operandEntered) {
        ($scope.leftOperand)
        ? $scope.rightOperand += operandEntered + " "
        : $scope.leftOperand += operandEntered + " ";
 console.log($scope.leftOperand,$scope.rightOperand);
    };



    $scope.setOperator = function (operatorEntered) {
        $scope.operator = operatorEntered;
    };

    $scope.getAnswer = function () {
        var result = $scope.leftOperand + $scope.operator + $scope.rightOperand;
        var answer = eval(result);

        if (answer % 1 !== 0){   // % 1 to identify floats
            $scope.answer = answer.toFixed(2);
        }
        else {$scope.answer = answer;}

        $scope.leftOperand = $scope.answer;
        $scope.operator = "";
        $scope.rightOperand = "";
    };

    $scope.setClear = function (a) {
          $scope.leftOperand = "";
          $scope.operator = "";
          $scope.rightOperand = "";
          $scope.answer = "";

    };


});

【问题讨论】:

  • 这个问题太宽泛了。您是在询问语法解析,还是在请人就更复杂的应用程序给您建议?如果您正在寻求建议,StackOverflow 是错误的地方。
  • 本质上,我问的是如何编写代码以使输入值大于一位操作数。几年前我自己在 Windows 环境中用 C 语言做过这个,所以我知道它可以做到。
  • 你真的应该尝试一下,所以你有一些代码可以展示。像这样的问题总是因为过于宽泛、基于意见或只是“为我编写代码”而被关闭。您可以通过在问题中将您的尝试显示为实际格式化的代码块来真正改善您的答案。
  • 将输入解析为字符串,比跟踪哪个点击属于哪个数字更容易
  • @Dale,不错的建议——我会去看看。

标签: javascript angularjs calculator


【解决方案1】:

您的第二个示例已经偏离了您的 (A B Operator) 语法。如果您打算保持一致以使解析更容易,它应该是

122 (233 41234 +) +

与任何编程语言一样,您需要开始做一些额外的解析工作,以解决您不能再简单地按空格分割的事实。如果你这样做了,你会得到

['122', '(233', '41234', '+)', '+']

解释如何解析您自己的领域特定语言 (DSL) 超出了此答案的范围。可以这么说,您可能想研究标记器以简化工作。

最后,这种嵌套语法可以用递归来处理。这意味着您获取解析的值并在“树”中搜索分支。如果你找到一个分支,就跟随它,如果它有一个分支,就跟随它,等等。继续跟随分支,直到你找到最深的节点。计算它们,然后将它们的值返回一个级别。继续递归地执行此操作,最终您将回到最顶层,并从所有这些子计算中留下一个值。您返回给用户的就是这个值。

就何时应该执行此操作而言,您可以在用户每次单击按钮时执行此操作,或者仅在用户单击计算器上的“计算”按钮时执行此操作。这取决于你。

【讨论】:

    【解决方案2】:

    这确实比我预期的要容易得多,并且不需要 onkeypress、ParseInt 或 ParseFloat。以下是最终奏效的方法:

    var calcApp = angular.module("calcApp", []);
    
    calcApp.controller("calcCtrl", function($scope) {
      $scope.leftOperand = "";
      $scope.operator = "";
      $scope.rightOperand = "";
      $scope.answer = "";
    
      var left = false; // flags
      var right = false;
    
      $scope.setOperand = function(operandEntered) {
        if (left == false && operandEntered >= 0 && operandEntered <= 9) {
          $scope.leftOperand += operandEntered;
          if (operandEntered == "") {
            left = true;
          }
        } else if (right == false) {
          $scope.rightOperand += operandEntered;
        }
      };
    
      $scope.setOperator = function(operatorEntered) {
        if (left == true && $scope.rightOperand) {
          $scope.operator = operatorEntered;
          right = true;
        }
        else if($scope.rightOperand=="")
        {
            left = true; // end of leftOperand input
        }
      };
    
      $scope.getAnswer = function() {
        var result = $scope.leftOperand + $scope.operator + $scope.rightOperand;
        var answer = eval(result);
    
        if (answer % 1 !== 0) {
          // % 1 to identify floats
          $scope.answer = answer.toFixed(2);
        } else {
          $scope.answer = answer;
        }
    
        $scope.leftOperand = $scope.answer;
        $scope.operator = "";
        $scope.rightOperand = "";
      };
    
      $scope.setClear = function() {
        $scope.leftOperand = "";
        $scope.operator = "";
        $scope.rightOperand = "";
        $scope.answer = "";
        left = false;
        right = false;
      };
    });
    #answerScreen {
      background-color: lightgray;
      border: 3px inset white;
      font: 23px Arial, Helvetica;
      font-weight: bold;
      height: 34px;
      padding-left: 3px;
      width: 215px;
    }
    
    button {
      border-radius: 10px;
      border-color: pink;
      font-weight: bold;
      height: 2em;
      width: 2em;
    }
    
    #rpn {
      text-align: center;
    }
    
    .calcButtonsrow {
      padding: 4px;
    }
    
    #calcButtonsBox {
      border-style: groove;
    }
    
    #clear {
      background-color: #FFAAAA;
    }
    
    body {
      padding-top: 7vh;
    }
    
    #space {
      background-color: #cff;
      text-align: center;
      padding: 0;
    }
    
    .overflow-hidden {
      overflow: hidden;
    }
    
    #plusSign,
    #multiplySign,
    #minusSign,
    #divideBySign {
      border-radius: 10px;
      font-weight: bold;
      height: 2em;
      width: 2em;
    }
    
    #plusSign:hover,
    #multiplySign:hover,
    #minusSign:hover,
    #equalSign:hover,
    #divideBySign:hover {
      background-color: #ff9;
      color: black;
    }
    
    #equalSign {
      color: #FA6800;
    }
    
    #modalCalcButt {
      height: 150px !important;
      width: 150px !important;
    }
    
    #OpenSource {
      font-weight: bold;
    }
    <html lang="en-us" ng-app="calcApp" class="full-height">
    
    <head>
      <title></title>
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    </head>
    
    
    <body>
      <div class="theCalculator" ng-controller="calcCtrl">
        <div class="calcButtonsrow" id="1stLine">
          <div id="answerScreen">
            <span>{{leftOperand}}</span>
            <span>{{rightOperand}}</span>
            <span>{{operator}}</span>
            <span>{{clear}}</span>
          </div>
        </div>
        <div><span>RPN Calculator - Usage: </span><span id="OpenSource">Number(s) {Sp} Number(s) {operator} {=}</span></div>
        <div class="calcButtonsrow" id="2ndLine">
          <button class="number" id="7" ng-click="setOperand('7')">7</button>
          <button class="number" id="8" ng-click="setOperand('8')">8</button>
          <button class="number" id="9" ng-click="setOperand('9')">9</button>
          <button id="divideBySign" ng-click="setOperator('/')" class=" operator">/</button>
        </div>
        <div class="calcButtonsrow" id="3rdLine">
          <button class="number" id="4" ng-click="setOperand('4')">4</button>
          <button class="number" id="5" ng-click="setOperand('5')">5</button>
          <button class="number" id="6" ng-click="setOperand('6')">6</button>
          <button id="multiplySign" ng-click="setOperator('*')" class=" operator">*</button>
        </div>
        <div class="calcButtonsrow" id="4thLine">
          <button class="number" id="1" ng-click="setOperand('1')">1</button>
          <button class="number" id="2" ng-click="setOperand('2')">2</button>
          <button class="number" id="3" ng-click="setOperand('3')">3</button>
          <button id="minusSign" ng-click="setOperator('-')" class=" operator">-</button>
    
        </div>
        <div class="calcButtonsrow" id="5thLine">
          <button id="clear" ng-click="setClear('C')">C</button>
          <button class="number" id="0" ng-click="setOperand('0')">0</button>
          <button id="equalSign" ng-click="getAnswer('=')" ng-disabled="!leftOperand || !rightOperand || !operator">=</button>
          <button id="plusSign" ng-click="setOperator('+')" class="operator">+</button>
          <button id="space" ng-click="setOperand('')" class="operator">Sp</button>
        </div>
      </div>
    
    
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js">
      </script>
    
    </body>
    
    </html>

    解决方案取决于为操作数设置两个标志。最初它们是错误的。当用户点击空格按钮时,具有讽刺意味的是,该按钮设置为空字符串,左侧标志设置为真以表示左侧操作数的输入结束。右操作数的输入结束由用户单击操作员按钮来标记。如果用户单击运算符而不是“Sp”按钮,该代码也很宽容,在这种情况下,左操作数的输入结束通过设置左标志来标记。请注意,如果用户选择了错误的运算符,代码允许轻松选择不同的运算符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多