可以有多个答案的冗余 if 语句的问题

Issue with redundant if statements that can have multiple answers

我必须编写一个程序,利用方法重载来计算圆柱体、球体、圆锥体和三角柱体的表面积和体积。我需要从用户那里获取输入,然后显示正确的表面积和体积。

程序应该做什么的一个例子是:

Input your shape’s “a” value: none
Input your shape’s “b” value: none
Input your shape’s “c” value: none
Input your shape’s “h” value: none
Input your shape’s “l” value: none
Input your shape’s “r” value: 5
Input your shape’s “s” value: none
Would you like your answer rounded?: yes
To what decimal place?: 0
---------------------------------------------------------------------
Your shape is a sphere!
It’s volume is 524 units cubed.
It’s surface area is 314 units squared.

我已经编写了程序的大部分代码,但我现在遇到的问题是每当我完成输入数据时,我都会收到错误消息:"Exception in thread "main" java.util.NoSuchElementException: 否找到线”。我怀疑问题出在我用来过滤用户给我的内容的 if 语句上,因为每个语句都可能多次出现相同的异常。因此,如果我想计算球体的体积,我唯一需要的输入是半径 r 的输入,所有其他输入都是 none。但是对于圆柱体,除了半径 r 和高度 h 之外,所有其他值也是 none。任何帮助将不胜感激。

到目前为止,这是我的代码:

import java.util.*;

class Main {

 String a = "none"; String b = "none"; String c = "none"; String h = "none"; String r = "none"; String s = "none"; String l = "none";
 String round;
 double aP; double bP; double cP; double hP; double rP; double sP; double lP;

 public static void main(String[] args) throws Exception{
   new Main();
 }//end main

 public Main() throws Exception{
   input();
   surfaceAreaPrint();
   volumePrint();

 }//end Main

 /**
  *
  */
 public void input() throws Exception{
   Scanner sc = new Scanner(System.in);
   System.out.print("");
   System.out.print("Input your shape’s “a” value: ");
   a = sc.nextLine();
   System.out.print("Input your shape’s “b” value: ");
   b = sc.nextLine();
   System.out.print("Input your shape’s “c” value: ");
   c = sc.nextLine();
   System.out.print("Input your shape’s “h” value: ");
   h = sc.nextLine();
   System.out.print("Input your shape’s “r” value: ");
   r = sc.nextLine();
   System.out.print("Input your shape’s “s” value: ");
   s = sc.nextLine();
   System.out.print("Input your shape’s “l” value: ");
   l = sc.nextLine();
   System.out.print("Would you like your answer rounded?: ");

   round = sc.nextLine();

   System.out.print("");
   System.out.print("");

   sc.close();
   parse();

 }//end input

  public void parse() throws Exception{
    System.out.println(a);
   aP = Double.parseDouble(a);
   bP = Double.parseDouble(b);
   cP = Double.parseDouble(c);
   hP = Double.parseDouble(h);
   rP = Double.parseDouble(r);
   sP = Double.parseDouble(s);
   lP = Double.parseDouble(l);

//cylinder
  if(a == "none" && b == "none" && c == "none" && s == "none" && l != "none") {
      surfaceAreaPrint();
      return;
    }

   //sphere
   else if (a.equalsIgnoreCase("none") && b.equalsIgnoreCase("none") && c.equalsIgnoreCase("none") && s.equalsIgnoreCase("none") && h.equalsIgnoreCase("none") && s.equalsIgnoreCase("none") && l.equalsIgnoreCase("none")){
surfaceAreaPrint();
return;

  }

  //cone
  else if (a.equalsIgnoreCase("none") && b.equalsIgnoreCase("none") && c.equalsIgnoreCase("none") && s.equalsIgnoreCase("none") && h.equalsIgnoreCase("none") && l.equalsIgnoreCase("none")){
     surfaceAreaPrint();
     return;
  }
  //traingular prism
  else if (r.equalsIgnoreCase("none") && s.equalsIgnoreCase("none")){
surfaceAreaPrint();
return;
   }


 }//end parse

 public void surfaceAreaPrint() throws Exception{
   Main s = new Main(); 
   System.out.println(s.surfaceArea(hP, rP));
   System.out.println(s.surfaceArea(rP));
   System.out.println(s.surfaceArea(hP, rP, sP));
   System.out.println(s.surfaceArea(aP, bP, cP, lP, hP));

 }//end surfaceAreaPrint

  public void volumePrint() throws Exception{
   Main s = new Main(); 
   System.out.println(s.surfaceArea(hP, rP));
   System.out.println(s.surfaceArea(rP));
   System.out.println(s.surfaceArea(hP, rP)); 
   System.out.println(s.surfaceArea(bP, lP, hP)); 

 }//end volumePrint

 //surface area for cylinder
 public double surfaceArea(double hP, double rP){
   return (2.0 * Math.PI * Math.pow(rP, 2.0)) + (2.0 * Math.PI * rP * hP);

 }//end surfaceArea

 //surface area for sphere
 public double surfaceArea(double rP){
   return (4.0 * Math.PI * Math.pow(rP, 2.0));

 }//end surfaceArea

 //surface area for cone
 public double surfaceArea(double hP, double rP, double sP){
   return (Math.PI * Math.pow(rP, 2.0)) + (Math.PI * rP * sP);

 }//end surfaceArea

   //surface area for traingular prism
 public double surfaceArea(double aP, double bP, double cP, double lP, double hp){
   return (bP * lP) + (aP * hP) + (bP * hP) + (cP* hP);

 }//end surfaceArea


 //volume for cylinder
 public double volume(double hP, double rP){
   return (Math.PI * Math.pow(rP, 2.0) * hP);

 }//end volume
 //volume for sphere
 public double volume(double rP){
   return ( 4.0 / 3.0 ) * Math.PI * Math.pow(rP, 3.0);

 }//end volume

 //volume for cone
 public double volume(double hP, double rP, double sP){
   return (1.0 / 3.0 ) * Math.PI * Math.pow(rP, 2.0) * hP;

 }//end volume

   //volume for traingular prism
  /**
   * calculates volume for traingular prism
   * @param times The number of times the die is to be rolled.
   * @return The results of rolling a 6-sided die.
   */
 public double volume(double aP, double bP, double cP, double lP, double hp){
   return (1.0 / 2.0 ) * bP * lP * hP;

 }//end volume

}//end Main

TL;DR

  • 在多个 if else 块中调用相同的方法是多余的(除非它们不 return,因此仍然可以调用所需的方法)
  • 很多时候可以简化长 if 条件,如果不能,最好将条件移动到其他方法 boolean isAThingIWant(..params) 以保持可读性
  • 不应在构造函数中调用 "business logic" 方法
  • 在成员方法中创建相同 class 的新对象可能会导致不需要的递归调用
  • 使用 System.in InputStream 关​​闭 Scanner 对象不允许将来从该流读取任何内容(参见 this
  • 尝试将 Double.parseDouble 与任何不是数字的字符串一起使用将导致 NumberFormatException,即使是工程记数法
  • OP 示例是一个单独的问题,但在设计 class 时,应使用适当的封装
  • 通常的做法是使用特定语言的编码标准(参见 this
  • 针对此问题的 OOP 方法是使用形状接口和其他 classes 实现它 - 这将允许使用继承和多态性的优势

原文:
最简单的解决方法是从下面的方法中删除 Main s = new Main(); 并使用 this 引用当前创建的对象,如下所示:

    public void surfaceAreaPrint() throws Exception{
//        Main s = new Main();
        System.out.println(this.surfaceArea(hP, rP));
        System.out.println(this.surfaceArea(rP));
        System.out.println(this.surfaceArea(hP, rP, sP));
        System.out.println(this.surfaceArea(aP, bP, cP, lP, hP));

    }//end surfaceAreaPrint

    public void volumePrint() throws Exception{
//        Main s = new Main();
        System.out.println(this.surfaceArea(hP, rP));
        System.out.println(this.surfaceArea(rP));
        System.out.println(this.surfaceArea(hP, rP));
        System.out.println(this.surfaceArea(bP, lP, hP));

    }//end volumePrint

实际上,您的示例中存在多个问题和代码异味。

另一件事是,您仍在 parse 方法的 if 语句中将字符串与 == 进行比较 - 使用 euqals or equalsIgnoreCase.

如果您的尝试实际上是通过上述方法从用户那里获取新输入,那么您将无法关闭扫描器,因为使用 System.in 关闭它会关闭它后面的 InputStream,因此它不再接受任何内容。我认为删除 sc.close() 会导致您遇到不同的异常和问题(例如,程序无法按您希望的方式运行)。

任何else if中的每条指令都使用相同的方法。因此整个if else if是多余的。

编辑:
刚刚检查过删除 sc.close() 并保持示例中的其余部分将导致无限获取用户输入,因为在 surfaceAreaPrint 中创建了新的 Main 对象并且从构造函数调用了输入Main 的,所以它变成了递归调用。

对于重载方法的使用,您可以这样简单地进行:

//cylinder
if(a.equalsIgnoreCase ("none") && b.equalsIg... rest of your if) {
    System.out.println(this.surfaceArea(hP, rP));
}

但请注意,当您在输入值并使用 sc.nextLine() 读取它们时只需按回车键时,分配的值将不会保持为 none,而是会变成一个空字符串,如 "",稍后将在 Double.parseDouble.

中的任何一个中抛出 NumberFormatException

编辑2:
现在,我看到您想在不使用该特定变量时严格输入 "none",因此为避免 NumerFormatException,您必须在检查字符串是否不是 [ 后将值解析为 double =95=].

您可以简化 if 语句,方法是将检查是否等于 "none" 更改为检查是否等于:

//for cylinder
if(!h.equalsIgnoreCase("none") && !r.equalsIgnoreCase("none") {
//....

对于真实几何对象的surface/volume的计算,可以假设定义它们大小的值应该是>=0,所以为了更简单的解析可以使用这样的方法:

public double inputParser(String s) {
    try {
        return Double.parseDouble(s);
    } catch (NumberFormatException e) {
        return -1;
    }
}
//and used instead of straight `Double.parseDouble`:
aP = inputParser(a);
bP = inputParser(b);
//which simplifies the `if` even more to:
if(hP != -1 && rP != -1) { //cylinder
    System.out.println(this.surfaceArea(hP, rP));
}

编辑 3:
经过几分钟的讨论并发现 OP 代码中的其他一些缺陷后,我制定了一个解决方案:

import java.util.*;
class Main {

    String a, b, c, h, r, s, l;
    String round;
    double aP; double bP; double cP; double hP; double rP; double sP; double lP;

    public static void main(String[] args) {
        Main m = new Main();
        m.input();
        m.parse();
        m.calculate();
    }

    public void input() {
        Scanner sc = new Scanner(System.in);
        System.out.print("");
        System.out.print("Input your shape’s “a” value: ");
        a = sc.nextLine();
        System.out.print("Input your shape’s “b” value: ");
        b = sc.nextLine();
        System.out.print("Input your shape’s “c” value: ");
        c = sc.nextLine();
        System.out.print("Input your shape’s “h” value: ");
        h = sc.nextLine();
        System.out.print("Input your shape’s “r” value: ");
        r = sc.nextLine();
        System.out.print("Input your shape’s “s” value: ");
        s = sc.nextLine();
        System.out.print("Input your shape’s “l” value: ");
        l = sc.nextLine();
        System.out.print("Would you like your answer rounded?: ");

        round = sc.nextLine();
        System.out.println("");

        sc.close();
    }

    public void parse() {
        System.out.println(a);
        aP = inputParser(a);
        bP = inputParser(b);
        cP = inputParser(c);
        hP = inputParser(h);
        rP = inputParser(r);
        sP = inputParser(s);
        lP = inputParser(l);
    }

    public void calculate() {
        if(hP != -1 && rP != -1) {
            System.out.println("Cylinder");
            System.out.println(this.rounding(this.surfaceArea(hP, rP)));
            System.out.println(this.rounding(this.volume(hP, rP)));
        }
        if (rP != -1){
            System.out.println("Sphere");
            System.out.println(this.surfaceArea(rP));
            System.out.println(this.volume(rP));
        }
        if (hP != -1 && rP != -1 && sP != -1){
            System.out.println("Cone");
            System.out.println(this.surfaceArea(hP, rP, sP));
            System.out.println(this.volume(hP, rP, sP));
        }
        if (aP != -1 &&  bP != -1 &&  cP != -1 &&  lP != -1 &&  hP != -1){
            System.out.println("Triangular prism");
            System.out.println(this.surfaceArea(aP, bP, cP, lP, hP));
            System.out.println(this.volume(aP, bP, cP, lP, hP));
        }
    }
    public double rounding(double value) {
        if ("yes".equalsIgnoreCase(round)) {
            return Math.round(value);
        }
        return value;
    }
    public double inputParser(String s) {
        try {
            return Double.parseDouble(s);
        } catch (NumberFormatException e) {
            return -1;
        }
    }
    //surface area for cylinder
    public double surfaceArea(double hP, double rP){
        return (2.0 * Math.PI * Math.pow(rP, 2.0)) + (2.0 * Math.PI * rP * hP);

    }//end surfaceArea

    //surface area for sphere
    public double surfaceArea(double rP){
        return (4.0 * Math.PI * Math.pow(rP, 2.0));

    }//end surfaceArea

    //surface area for cone
    public double surfaceArea(double hP, double rP, double sP){
        return (Math.PI * Math.pow(rP, 2.0)) + (Math.PI * rP * sP);

    }//end surfaceArea

    //surface area for traingular prism
    public double surfaceArea(double aP, double bP, double cP, double lP, double hp){
        return (bP * lP) + (aP * hP) + (bP * hP) + (cP* hP);

    }//end surfaceArea


    //volume for cylinder
    public double volume(double hP, double rP){
        return (Math.PI * Math.pow(rP, 2.0) * hP);

    }//end volume
    //volume for sphere
    public double volume(double rP){
        return ( 4.0 / 3.0 ) * Math.PI * Math.pow(rP, 3.0);

    }//end volume

    //volume for cone
    public double volume(double hP, double rP, double sP){
        return (1.0 / 3.0 ) * Math.PI * Math.pow(rP, 2.0) * hP;

    }//end volume

    //volume for traingular prism
    public double volume(double aP, double bP, double cP, double lP, double hp){
        return (1.0 / 2.0 ) * bP * lP * hP;

    }//end volume

}//end Main

还不是最好的,有封装、变量命名等一些问题,但很好地解决了问题。