简体   繁体   English

为什么我的程序不返回表达式的值?

[英]Why isn't my program returning the value of my expression?

I am currently taking an AP Computer Science class in my school and I ran into a little trouble with one of my projects! 我目前正在我的学校上一门AP计算机科学课,而我的一个项目遇到了一些麻烦! The project requires me to create a calculator that can evaluate an expression and then solve it. 该项目要求我创建一个可以对表达式求值然后求解的计算器。 I have got most of that down, but I ran into a little trouble because my teacher asked me to use a while loop to continuously ask for input and display the answer, and I am stuck on that. 我大部分时间都花在了这里,但是我遇到了一个麻烦,因为我的老师要求我使用while循环来不断地要求输入并显示答案,而我对此感到困惑。 To end the program the user has to type in "quit" and I can't use system.exit() or any cheating thing like that, the program has to just run out of code. 要结束该程序,用户必须输入“ quit”,并且我不能使用system.exit()或类似的作弊手段,该程序必须耗尽代码。 I have got most of that down too, but I am not able to find a why to return the expression in the Method MethodToReadInput(); 我也已经了解了大部分,但是我找不到在方法MethodToReadInput(); return expression的原因MethodToReadInput(); Does anyone have any tips? 有人有提示吗?

import java.util.*;

public class Calculator {
   public static void main(String[] args) {
      System.out.println("Welcome to the AP Computer Science calculator!!");
      System.out.println();
      System.out.println("Please use the following format in your expressions: (double)(space)(+,-,*,/...)(space)(double)");
      System.out.println("or: (symbol)(space)(double)");
      System.out.println();
      MethodToReadInput();
      MethodToTestInput(MethodToReadInput());

   }

   public static String MethodToReadInput() {
      Scanner kb = new Scanner(System.in);
      System.out.print("Enter an expression, or quit to exit: ");
      String expression = kb.nextLine();
      if (expression.equalsIgnoreCase("quit")) {
         System.out.println("Goodbye!");
      }
      else {
         return expression; 
      }
   } 
   public static void MethodToTestInput(String expression) {
      while (!expression.equalsIgnoreCase("quit")) {
          MethodToReadInput();
          MethodtoEvaluateInput(expression);
      }
      System.out.println("Goodbye!");
   }



   public static void MethodtoEvaluateInput(String expression) {
      if (OperatorFor2OperandExpressions(expression).equals("+")) {
         System.out.println(FirstOperandFor2OperandExpressions(expression) + " " + OperatorFor2OperandExpressions(expression) + " " + SecondOperandFor2OperandExpressions(expression) + " = " + (FirstOperandFor2OperandExpressions(expression) + SecondOperandFor2OperandExpressions(expression)));          
      }
      else if (OperatorFor2OperandExpressions(expression).equals("*")) {
         System.out.println(FirstOperandFor2OperandExpressions(expression) + " " + OperatorFor2OperandExpressions(expression) + " "  + SecondOperandFor2OperandExpressions(expression) + " = " + (FirstOperandFor2OperandExpressions(expression) * SecondOperandFor2OperandExpressions(expression)));
      }
      else if (OperatorFor2OperandExpressions(expression).equals("-")) {
         System.out.println(FirstOperandFor2OperandExpressions(expression) + " " + OperatorFor2OperandExpressions(expression) + " " + SecondOperandFor2OperandExpressions(expression) + " = " + (FirstOperandFor2OperandExpressions(expression) - SecondOperandFor2OperandExpressions(expression)));       
      }
      else if (OperatorFor2OperandExpressions(expression).equals("/")) {
         System.out.println(FirstOperandFor2OperandExpressions(expression) + " " + OperatorFor2OperandExpressions(expression) + " "  + SecondOperandFor2OperandExpressions(expression) + " = " + (FirstOperandFor2OperandExpressions(expression) / SecondOperandFor2OperandExpressions(expression)));
      }
      else if (OperatorFor2OperandExpressions(expression).equals("^")) {
         System.out.println(FirstOperandFor2OperandExpressions(expression) + " " + OperatorFor2OperandExpressions(expression) + " " + SecondOperandFor2OperandExpressions(expression) + " = " + Math.pow(FirstOperandFor2OperandExpressions(expression),SecondOperandFor2OperandExpressions(expression)));
      }
      else if (OperatorFor1OperandExpressions(expression).equals("|")) {
         System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + Math.abs(OperandFor1OperatorExpressions(expression)));
      }
      else if (OperatorFor1OperandExpressions(expression).equals("v")) {
         System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + Math.sqrt(OperandFor1OperatorExpressions(expression)));
      }
      else if (OperatorFor1OperandExpressions(expression).equals("~")) {
         double x = 0.0;
         System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + (Math.round(OperandFor1OperatorExpressions(expression))+ x));
      }
      else if (OperatorFor1OperandExpressions(expression).equals("s")) {
         System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + Math.sin(OperandFor1OperatorExpressions(expression)));
      }
      else if (OperatorFor1OperandExpressions(expression).equals("c")) {
         System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + Math.cos(OperandFor1OperatorExpressions(expression)));
      }
      else if (OperatorFor1OperandExpressions(expression).equals("t")) {
         System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + Math.tan(OperandFor1OperatorExpressions(expression))); 
      } 
   }

      public static double FirstOperandFor2OperandExpressions(String expression) {
         String[] tokens = expression.split(" ");
         String OperandOrOperator = tokens[0];
         double y = Double.parseDouble(OperandOrOperator);
         return y;         
   }
      public static double SecondOperandFor2OperandExpressions(String expression) {
         String[] tokens = expression.split(" ");
         String OperandOrOperator = tokens[2];
         double y = Double.parseDouble(OperandOrOperator);
         return y;
   }
       public static String OperatorFor2OperandExpressions(String expression) {
         String[] tokens = expression.split(" ");
         String OperandOrOperator = tokens[1];
         return OperandOrOperator;
   }
      public static String OperatorFor1OperandExpressions(String expression) {
         String[] tokens = expression.split(" ");
         String OperandOrOperator = tokens[0];
         return OperandOrOperator; 
   }
      public static double OperandFor1OperatorExpressions(String expression) {
         String[] tokens = expression.split(" ");
         String OperandOrOperator = tokens[1];
         double y = Double.parseDouble(OperandOrOperator);
         return y;  
   }           
}

You need to put the MethodToReadInput and MethodtoEvaluateInput inside a loop. 您需要将MethodToReadInputMethodtoEvaluateInput放入循环中。 For example: 例如:

public static void main(String[] args)
{
    System.out.println("Welcome to the AP Computer Science calculator!!");
    System.out.println();
    System.out.println("Please use the following format in your expressions: (double)(space)(+,-,*,/...)(space)(double)");
    System.out.println("or: (symbol)(space)(double)");
    System.out.println();


    String input = MethodToReadInput();
    while (input != null)//exit the loop and the program when input is null
    {
        MethodtoEvaluateInput(input);//process the input
        input = MethodToReadInput();//ask the user for the next input
    }

}

public static String MethodToReadInput()
{
    Scanner kb = null;
    try
    {
        kb = new Scanner(System.in);
        System.out.print("Enter an expression, or quit to exit: ");
        String expression = kb.nextLine();
        if (expression.equalsIgnoreCase("quit"))
        {
            System.out.println("Goodbye!");
            return null;
        }
        else
        {
            return expression;
        }

    }
    finally
    {//always close the Scanner before leaving the method
        if (kb != null)
            kb.close();
    }
}

Also, you should follow the Java Naming Convention and use shorter names for your methods. 另外,您应遵循Java命名约定并为您的方法使用较短的名称。

Do this: 做这个:

 public static String MethodToReadInput() {
      Scanner kb = new Scanner(System.in);
      System.out.print("Enter an expression, or quit to exit: ");
      String expression = kb.nextLine();
      if (expression.equalsIgnoreCase("quit")) {
         System.out.println("Goodbye!");
         return "";
      }
      else {
         return expression; 
      }

By returning an empty string you know what to look for when the user wants to exit. 通过返回一个空字符串,您知道当用户想要退出时要查找的内容。 It needs to be an empty string that you return because your method is supposed to return a string. 它必须是您返回的空字符串,因为您的方法应该返回一个字符串。 Also adding this return statement is needed because the compiler will complain otherwise because it is possible to reach the end of a non-void function (something that returns something) without actually reaching a return statement (so when you enter the if statement as you have it now). 还需要添加此return语句,因为编译器会抱怨否则,因为有可能到达非空函数(返回某些内容)的末尾而没有实际到达return语句的情况(因此,当您输入if语句时,现在)。 You must specify a return case for all possibilities if you specify a return type. 如果指定返回类型,则必须为所有可能性指定一个返回案例。 In other words you must always return what you say you will. 换句话说,您必须始终返回您所说的话。

Try to simplify your code, and use do-while-loop instead while-loop should produce a better code, do while will at least do one loop and then inspect the next condition before do the next loop, but while will inspect the condition first, if it is okay, it will do the loop. 尝试简化您的代码,并使用do-while-loop代替while-loop应该会生成更好的代码,do while将至少执行一个循环,然后在执行下一个循环之前检查下一个条件,但是while将首先检查条件,如果可以,它将执行循环。 So here is the code: 所以这是代码:

public class Calculator {
    public static void main(String[] args) throws IOException {
        System.out.println("Welcome to the AP Computer Science calculator!!");
        System.out.println();
        System.out.println("Please use the following format in your expressions: (double)(space)(+,-,*,/...)(space)(double)");
        System.out.println("or: (symbol)(space)(double)");
        System.out.println();

        String expression = "";
        do {
            Scanner kb = new Scanner(System.in);
            System.out.print("Enter an expression, or quit to exit: ");
            expression = kb.nextLine();
            if (expression.equalsIgnoreCase("quit")) 
                System.out.println("Goodbye!");
            else 
                MethodtoEvaluateInput(expression);              
        } while (!expression.equalsIgnoreCase("quit"));
        inRn.close();
        inSw.close();
    }
}

There are several things that should be fixed about this. 关于此问题,应该修复几件事。

First, let's answer your actual question. 首先,让我们回答您的实际问题。 You can have a number of choices. 您可以有多种选择。

  • You can just simply return whatever the user has input. 您只需返回用户输入的内容即可。 In fact, you may not actually need the method for this. 实际上,您实际上可能不需要此方法。 But anyway, if your method returns "quit", the while loop can check while ( ! expression.equals("quit") ) just as it does now. 但是无论如何,如果您的方法返回“ quit”,则while循环可以像现在一样检查while ( ! expression.equals("quit") )
  • You could return null. 您可以返回null。 This indicates that "The expression is not an actual expression". 这表示“该表达式不是实际的表达式”。 Then your while could be while ( expression != null ) which is more efficient than string comparison. 然后your while可能是while ( expression != null ) ,它比字符串比较更有效。

But you have other design issues with your program: 但是您的程序还有其他设计问题:

  1. You are calling the same methods again and again to retrieve the same things. 您一次又一次调用相同的方法来检索相同的东西。 Those methods split the string - a relatively heavy operation - again and again. 这些方法一遍又一遍地分割字符串(相对繁重的操作)。 You should probably just have a parseExpression() method that returns your tokens, and then something that tests whether these tokens represent a unary operator or a binary one. 您可能应该只具有一个parseExpression()方法来返回您的令牌,然后再测试这些令牌是表示一元运算符还是二进制运算符。 Something along the lines of: 类似于以下内容:

     String [] tokens = parseExpression( expression ); if ( isUnaryExpression( tokens ) ) { String operator = tokens[0]; String operand = tokens[1]; // Do something with operator and operand. } else if ( isBinaryExpression( tokens ) ) { String operator = tokens[1]; String operand1 = tokens[0]; String operand2 = tokens[2]; // Do something with operator and operands { } else { System.err.println( "Bad expression!" ); } 
  2. You are calling MethodToReadInput twice from your main. 您从主系统调用MethodToReadInput两次MethodToReadInput This means it will Read one input, do nothing about it, and then read another one which will be passed to MethodToTestInput . 这意味着它将读取一个输入,不执行任何操作,然后读取另一个将传递给MethodToTestInput Drop the first call, it's unnecessary. 挂断第一个电话,没有必要。

  3. In the cause of better encapsulation, the main method should actually not even call MethodToReadInput . 为了更好地封装, main方法实际上甚MethodToReadInput不应调用MethodToReadInput It should become the responsibility of MethodToTestInput to call that method. 调用该方法应该成为MethodToTestInput的责任。 So you just call MethodToTestInput() from main without passing a parameter at all. 因此,您只需从main调用MethodToTestInput() ,而无需传递任何参数。

So the structure should be: 因此,结构应为:

  • main : Display introduction, call your looping method. main :显示简介,调用您的循环方法。
  • looping method : Call input method. 循环方法 :调用输入法。 Loop while returned expression is still an expression rather than "quit" . 当返回的表达式仍然是表达式而不是"quit"循环。 Inside the loop, call expression handler method. 在循环内部,调用表达式处理程序方法。
  • expression handler method : Call parseExpression() method, check what the tokens are, do the math. 表达式处理程序方法 :调用parseExpression()方法,检查标记是什么,进行数学运算。

Finally, about your naming issues: 最后,关于您的命名问题:

  • In Java, we name only classes with an uppercase first letter. 在Java中,我们只命名首字母大写的类。 Constants are named with all capitals (words separated by underscore). 常量以所有大写字母(用下划线分隔的单词)命名。 Method names begin with a lowercase letter. 方法名称以小写字母开头。
  • You don't name a method MethodThatDoesThis . 您没有将方法命名为MethodThatDoesThis You should name it doThis , instead. 您应该将其命名为doThis This makes reading your code easier because it actually describe what is happening. 这使阅读代码变得更容易,因为它实际上描述了正在发生的事情。 So I'd name the methods something like: 所以我将这些方法命名为:

    • The input method: getNextExpression 输入方法: getNextExpression
    • The looping method: runCalculator , or doCalculatorMainLoop or something like that. 循环方法: runCalculatordoCalculatorMainLoop或类似的方法。
    • The expression handler method: parseAndCalculate . 表达式处理程序方法: parseAndCalculate

    Or something along these lines. 或类似的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM