【问题标题】:Why is the function being called multiple times in a loop?为什么函数在循环中被多次调用?
【发布时间】:2019-01-30 10:54:00
【问题描述】:

我已经使用处理开发环境制作了一个图形计算器应用程序,并包含了一个 Java Operation 类。然后我在我的主文件-calculator.pde 中调用了Operation 类的实例。 当我在多个实例上调用该方法时,有条件地,由于调用该方法的循环和条件,它会多次打印该方法的输出。

这是Operation 类的calculate() 方法:

String calculate() {
    int operationIndex = userInput.indexOf(operationSymbol);
    ArrayList<String> clickedNumbers = new ArrayList<String>();
    System.out.println(operation + " index: " + operationIndex);
    for (int i = 0; i < operationIndex; i++) {
      clickedNumbers.add(userInput.get(i));         }
    double double1 = calculator.stringToDouble(String.join("", clickedNumbers)); 
    System.out.println("double1: " + double1);
    clickedNumbers.clear();
    int equalsIndex = userInput.indexOf("=");
    for (int i = operationIndex + 1; i < equalsIndex; i++) {
      clickedNumbers.add(userInput.get(i));
    }
    double double2 = calculator.stringToDouble(String.join("", clickedNumbers)); 
    System.out.println("double2: " + double2);
    Double operResult = this.doOperation(double1, double2);
    String operationResult = calculator.doubleToString(operResult);
    System.out.println("Operation Result: " + operationResult);
    return operationResult;
}

所有System.out.println() 语句都依赖于方法内的局部变量。这些应该只打印到控制台一次。每当用户输入一个操作并按下等于时,例如,如果他/她输入15 * 3,它就会输出:

上面,控制台输出的高亮部分是我想要的输出。

这是我调用 calculate() 方法的代码:

  String[] numberStr = {"1", "2", "3", "4", "5", "6", "7", "8", "9"};
  Boolean pressedEquals = listName.contains("=");

  for(String number : numberStr) {
  Boolean pressedNumber = listName.contains(number);
    if (pressedNumber && pressedEquals) {
      if (listName.contains("+")) {
        processStatement = "Adding Numbers...";
        result = addition.calculate();
      }
      else if (listName.contains("-")) {
        processStatement = "Subtracting Numbers...";
        result = subtraction.calculate();
      }
      else if (listName.contains("*")) {
        processStatement = "Multiplying Numbers...";
        result = multiplication.calculate();
      }
      else if (listName.contains("/")) {
        processStatement = "Dividing Numbers...";
        result = division.calculate();
      }
      else if (listName.contains("%")) {
        processStatement = "Modulufying Numbers...";
        result = modulus.calculate();
      }
      else if (listName.contains("^")) {
        processStatement = "Expounding numbers...";
        result = exponential.calculate();
      }
    } 
  }

我不明白为什么它打印输出的次数是userInputArrayList 的长度。我知道问题是for 循环中的pressedNumber 布尔值。我知道this question 上的 OP 也有同样的问题,它会根据用户输入的长度打印多次,但问题的答案并没有解释它为什么这样做。

无效的研究和试验

解决这个问题的一部分是将processStatement 变成一个变量,因为之前我只是在条件中打印它。这不起作用,因为它打印了多次。我不能对方法内部的println 语句执行此操作,因为它们依赖于方法内部的变量,并且语句数量很多。我的第二个计划是创建一个静态方法printInfo(),但这也行不通,因为变量的范围太窄,我不能在外面定义它们,因为那样就不准确了。

更新

我更多地研究了堆栈溢出,这次是正则表达式,这些问题添加到我的研究中以解决这个问题:

【问题讨论】:

  • 好吧,从纯 Java 的角度来看,如果你在循环中被调用,打印一次是没有意义的。解决方案是根本不打印任何内容,让调用代码而不是函数来进行打印。
  • 更好的问题是“为什么函数在一个循环中被多次调用?”
  • @markspace 你能在答案中解释更多吗?
  • @markspace 它应该只打印一次,因为 print 语句是在循环中的条件下调用的。条件包含循环的计数器 (number)。
  • 顺便说一下,我强烈建议遵循 Java 命名约定:变量名和方法总是以小写字母开头。所以ClickedNumbers 应该是clickedNumbersStringToDouble 应该是stringToDouble

标签: java regex loops parsing processing


【解决方案1】:

您可能需要在代码中重新考虑以下几点:

比如看看这个sn-p:

String[] numberStr = {"1", "2", "3", "4", "5", "6", "7", "8", "9"};
Boolean pressedEquals = listName.contains("=");

for(String number : numberStr) {
    Boolean pressedNumber = listName.contains(number);
    // ...
}

这里不需要这个循环。您可以简单地验证 listName 是否包含数字、运算符,即它是一个有效的表达式。然后,如果有效,则只需调用 calculate() 方法。您还可以使用基于正则表达式的验证来强制执行您的特定表达式格式。

跳过该循环并执行验证后,它将如下所示:

// Validate expression format here
// Example: <number> <operator> <number> <=>
//             1          *        5      =

final boolean isValidated = isValidExpression( /* expression */ );

if ( isValidated == true )
{
    final String op = /* get operator here */;
    switch ( op )
    {
        case "+":
            result = addition.calculate();
            break;

        case "-":
            result = subtraction.calculate();
            break;

       // ... /, *, % ...

        default:
            // ERROR: Invalid operator...
    }
}

除此之外,您还可以使用基于堆栈的表达式求值。


更新:

这是一个带有正则表达式的isValidExpression() 方法示例:

// Test to validate expression with regex
// Example: <number> <operator> <number> <=>
//             1          *        5      =

import java.util.regex.Matcher;
import java.util.regex.Pattern;

class ExpressionValidator
{
    public static boolean isValidExpression( final String exp )
    {
        final String regex = "\\d+\\s*[*|/|+|-]\\s*\\d+\\s*[=]";
        final Pattern pattern = Pattern.compile( regex );
        final Matcher matcher = pattern.matcher( exp.trim() );
        return matcher.find();
    }

    public static void main( final String[] args )
    {
        final String[] expressions = 
        {  
            " 1 +  2 =",
            " 3 *  5 =",
            "12 + 10 =",
            " 33 = 25 ",
            " +65  65 ",
            "45 666  ="
        };

        for ( final String exp : expressions )
        {
            System.out.println( "[" + exp + "] >> " + isValidExpression( exp ) );
        }
    }
}

输出:

[ 1 +  2 =] >> true
[ 3 *  5 =] >> true
[12 + 10 =] >> true
[ 33 = 25 ] >> false
[ +65  65 ] >> false
[45 666  =] >> false

以下是实际示例:https://ideone.com/S9Wf9b

【讨论】:

  • 感谢 Azeem 的回答。我查了一下,似乎 validateExpression 不是一个实际的方法,所以,我必须为此创建自己的函数吗?如果是,我是否只需在此处键入 return ? Also, I would not use final String op`,因为我的 calculate 方法中已经有了它。
  • 错误:calculator.pde:115:0:115:0:函数 validateExpression(String) 不存在。我输入了以下代码String listString = String.join(", ", listName); final boolean isValidated = validateExpression(listString); if (isValidated == true) { if (listName.contains("+")) {
  • @Marvin :这只是一个想法。您必须编写自己的验证函数。可以使用Java的正则表达式。
  • 您能否在回答中解释如何使用正则表达式,因为我以前从未使用过它们。或者给我一个在线链接。我找不到任何关于 RegEx 语法的教程。谢谢
  • @Marvin:我添加了一个示例来使用正则表达式验证输入表达式。希望有帮助!
猜你喜欢
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多