1

I have to code a program that utilizes method overloading to calculate the surface area and volume of a cylinder, sphere, cone and triangular prism. I need to take input from the user and then display the correct surface area and volume.

An example of what the program should do is:

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.

I've coded the majority of the program, but the issue I'm having now is whenever I finish inputting the data, I get the error: "Exception in thread "main" java.util.NoSuchElementException: No line found". I suspect the issue is with the if statements I've used to filter through what the user has given me, as each one can have the same exceptions multiple times. So if I want to calculate the volume of a sphere the only input I need is to that of the radius, r, and all others are none. But all others are none as well for a cylinder except for the radius, r, and the height, h. Any help would be much appreciated.

This is my code so far:

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
mrgasmaskdude
  • 57
  • 1
  • 6

1 Answers1

4

TL;DR

  • calling the same method inside multiple if else blocks is redundant (until they doesnt return, so the required method could still be called)
  • many times the long if condition can be simplified, if not it's better to move the condition to additional method boolean isAThingIWant(..params) to maintain readability
  • the "business logic" method shouldn't be called in constructor
  • creating new objects of same class inside member methods can lead to unwanted recursive calls
  • closing the Scanner object with a System.in InputStream disallows for any future reads from that stream (see this)
  • trying to use Double.parseDouble with any string which isn't a number will cause NumberFormatException, even for engineering notation
  • the OP example is a separated problem, but when designing an class, a propper encapsulations should be used
  • common practice is to use a coding standards for particular language (see this)
  • OOP approach for this problem would be to use shape interface and additional classes implementing it - which would allow to use advantages of inheritance and polymorphism

Original:
The simplest fix is to remove the Main s = new Main(); from below methods and use the this reference for currently created object like below:

    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

Actually, there are several issues and code smells in your example.

Another thing is that your are still comparing strings with == in the if statement in parse method - use the euqals or equalsIgnoreCase.

If your attempt was actually get new input from user in above methods then you cannot close the scanner, because closing it with the System.in closes the InputStream behind it, so it doesn't accept anything more. I think that deleting the sc.close() can lead you to different exceptions and issues (e.g. program won't work as you want it to).

Each instructions in any else if there are using same method. Therefore whole if else if is redundant.

Edit:
Just checked that removing the sc.close() and keeping the rest as it is in your example will lead to infinite getting of the user input, because of creating new Main object in surfaceAreaPrint and the input is called from the constructor of Main, so it becomes at recursive calls.

For the using of overloaded method you can go simply like this:

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

But note that, when you just press enter when inputing the values and reading them with sc.nextLine(), the assigned value wont stay as none but will become an empty string like "", which will throw NumberFormatException later in any of Double.parseDouble.

Edit2:
Now, I see that you want to strictly input "none" when you won't use that particular variable, so to avoid NumerFormatException you must parse the values to double after you check if the string isn't "none".

You can simplify the if statements by changing the check if they equal to "none" to check if they dont:

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

For the calculation of surface/volume of real geometrical objects, you can assume that values defining their size should be >=0, so for simpler parsing the such method could be used:

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));
}

Edit3:
After few minutes of discussion and discovering some other flaws in the OP code I made a solution:

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

Still not the best one, have encapsulation, variable naming and some other issues, but covers the problem well.

itwasntme
  • 1,454
  • 4
  • 19
  • 24
  • Thank you for the response, I've implemented the suggestions you gave and have also tried using the sc.hasNextLine(), but unfortunately am still getting the same error. I think I understand now that all the else if statements are redundant, so my question now is how do I call the correct overloaded method for calculating the correct surface area and volume? Any more help would be tremendous. – mrgasmaskdude Jan 19 '20 at 20:09
  • 1
    @mrgasmaskdude are you getting NoSuchElementException after changing the `surfaceAreaPrint` and `volumePrint` to the ones I provided? – itwasntme Jan 19 '20 at 20:18
  • I've made the changes specified, but unfortunately the code still doesn't work. For almost every other method assignment I've done this has worked, but for some reason this still doesn't. – mrgasmaskdude Jan 19 '20 at 20:47
  • 1
    @mrgasmaskdude ehh, k, I can take a look at it, post it on some kind of pastebin – itwasntme Jan 19 '20 at 20:48
  • Is it possible to just give you a link to the code itself? – mrgasmaskdude Jan 19 '20 at 20:49
  • @mrgasmaskdude and additionally is your desired output like `282.7433388230814 282.7433388230814 314.1592653589793`, and you nowhere use the `round` variable later – itwasntme Jan 19 '20 at 20:49
  • I'm coding that part right now, I first wanted to resolve the current error I'm having. Heres the link: https://repl.it/@NeilCampbell/testoverloading2 – mrgasmaskdude Jan 19 '20 at 20:51
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/206241/discussion-between-itwasntme-and-mrgasmaskdude). Come here – itwasntme Jan 19 '20 at 20:53