I'm new to java and was trying to do this program. Basically entering 3 numbers, it will calculate the volume of a cube. If a negative number is typed then it will throw an exception, and also when there are more then 3 input. I wanted it to throw an exception also, if the input is not a number, but I have no idea how to store the input inside a variable and then check if it's a string and eventually throw an exception. Any suggestions? Here's my code
public class CubeVolume
{
public static void main(String [] args)
{
try
{
// try if there is more than 3 arguments
int width = Integer.parseInt(args[0]);
int depth = Integer.parseInt(args[1]);
int hight = Integer.parseInt(args[2]);
if (args.length > 3)
throw new ArrayIndexOutOfBoundsException
("You have supplied " + args.length + " arguments!");
// try if there is less than 3 arguments
if (args.length < 3)
throw new ArrayIndexOutOfBoundsException
("You have supplied " + args.length + " arguments!");
// checks if the width entered is equal or less than 0
if (width <= 0)
throw new NumberFormatException
("The argument " + width + " is a negative number!");
// checks if the depth entered is equal or less than 0
if (depth <= 0)
throw new NumberFormatException
("The argument " + depth + " is a negative number!");
// checks if the hight entered is equal or less than 0
if (hight <= 0)
throw new NumberFormatException
("The argument " + hight + " is a negative number!");
int volume = width * depth * hight;
System.out.println("The volume of a cube with dimensions " + "(" + width
+ "," + hight + "," + depth + ") " + "is " + volume);
} // try
// if there's one than more argument error will be displayed
catch (ArrayIndexOutOfBoundsException exception)
{
System.out.println("Please supply width, depth and hight arguments!");
System.out.println("Exception message was: '" + exception.getMessage()
+ "'");
System.err.println(exception);
} // catch
// if a negative number is entered error will be displayed
catch (NumberFormatException exception)
{
System.out.println("Dimensions for a cube can't be negative, please "
+ "insert only positive whole numbers!");
System.out.println("Exception message was: '" + exception.getMessage()
+ "'");
System.err.println(exception);
} // catch
} // main
} // CubeMain
This:
int width = Integer.parseInt(args[0]);
already throws a NumberFormatException if the String in question is not a valid string representation of an integer.
EDIT:
To address your comments:
public class CubeVolume {
private int width;
private int depth;
private int height;
public static void main(String [] args) {
if (args.length != 3) {
throw new Exception("Width, height and depth are required arguments");
}
width = Integer.parseInt(args[0]);
depth = Integer.parseInt(args[1]);
height = Integer.parseInt(args[2]);
// more stuff here
}
}
You can create your own exception class and throw the instance of that class from a method.
The exception class:
// Extending Exception makes your class throwable
class MyException extends Exception {
public MyException( String string ) {
super( string );
}
}
And for parsing the input string to integer, call a method like this :
int width = parseInt(args[0]);
where your parseInt() method throws your custom exception as follows:
private int parseInt( String number ) throws Exception {
try {
return Integer.parseInt( number );
} catch ( Exception e ) {
throw new MyException( "The input is not a number" );
}
}
Now, you can catch your custom exception MyException similar to other standard exceptions:
// catching your custom exception
catch ( MyException e ) {
System.err.println( e );
}
// if there's one than more argument error will be displayed
catch (ArrayIndexOutOfBoundsException exception)
{
System.out.println("Please supply width, depth and hight arguments!");
System.out.println("Exception message was: '" + exception.getMessage()
+ "'");
System.err.println(exception);
} // catch
// if a negative number is entered error will be displayed
catch (NumberFormatException exception)
{
System.out.println("Dimensions for a cube can't be negative, please "
+ "insert only positive whole numbers!");
System.out.println("Exception message was: '" + exception.getMessage()
+ "'");
System.err.println(exception);
} // catch
Related
I'm trying to make a program that will allow the user to input either a name or symbol of an element from the periodic table, and will then output some data about that element. So far I've managed to get the user to be able to input either a name or a symbol and have it output correctly, but if the user inputs something wrong then the code doesn't output anything, and will stop accepting an input of a symbol and only accept an input of a name. I would like to know how I would be able to break out of the loop and tell a user that their input is invalid only after the input has been checked against every item in the enum, since my current solution doesn't work. I'm new to Java, so a simple explanation as to how and why would be greatly appreciated.
import java.util.Scanner;
public class PeriodicTable {
public enum Element {
Hydrogen("H", "Nonmetal", "1.008"),
Helium("He", "Noble Gas", "4.003"),
Lithium("Li", "Alkali Metal", "6.941"),
Beryllium("Be", "Alkaline Earth", "9.012"),
Boron("B", "Semimetal", "10.811"),
Carbon("C", "Nonmetal", "12.011"),
//The rest of the periodic table is here, I just removed it for the sake of this post.
private String symbol;
private String group;
private String weight;
private Element(String symbol, String group, String weight) {
this.symbol = symbol;
this.group = group;
this.weight = weight;
}
}
static Element cName = null;
public static void main(String[] args) {
int counter = 0;
System.out.println("Enter the name or symbol of an element in the periodic table. ");
outer:
do {
Scanner reader = new Scanner(System.in);
String input = reader.nextLine().trim();
for (Element sy : Element.values()) {
if (sy.symbol.equalsIgnoreCase(input)) {
System.out.println("Element: " + sy + " (" + sy.symbol + ")" + "\nGroup: " + sy.group + "\nAtomic Mass: " + sy.weight);
reader.close();
break outer;
} else {
try {
cName = Element.valueOf(input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase());
System.out.println("Element: " + cName + " (" + cName.symbol + ")" + "\nGroup: " + cName.group + "\nAtomic Mass: " + cName.weight);
reader.close();
break outer;
} catch(IllegalArgumentException e) {
if(counter > Element.values().length) {
System.out.println("That name or symbol is not valid. Please try again. ");
continue outer;
} else {
counter++;
continue;
}
}
}
}
} while (true);
}
}
I would avoid using the valueOf method in a loop. Instead, you can iterate over the elements and for each element check both its name (use the name method) and its symbol.
Scanner reader = new Scanner(System.in);
outer: while (true) {
System.out.println("Enter the name or symbol of an element in the periodic table. ");
String input = reader.nextLine().trim();
for (Element sy : Element.values()) {
if (sy.symbol.equalsIgnoreCase(input) || sy.name().equalsIgnoreCase(input)) {
System.out.println("Element: " + sy + " (" + sy.symbol + ")" + "\nGroup: " + sy.group + "\nAtomic Mass: " + sy.weight);
break outer;
}
}
System.out.println("No such element found. ");
}
reader.close(); // this might be a bad idea
I would also avoid closing the reader, as this will also close System.in and you will be unable to read any more input.
Assuming I understand your question, I would add the logic for parsing Element(s) to Element. You can create Map(s), one to symbol and one of name to corresponding Element instances and then invoke them in whichever order you choose. Like,
private static Map<String, Element> symbolMap = new HashMap<>();
private static Map<String, Element> nameMap = new HashMap<>();
static {
for (Element e : Element.values()) {
symbolMap.put(e.symbol.toUpperCase(), e);
nameMap.put(e.name().toUpperCase(), e);
}
}
public static Element fromString(String token) {
if (symbolMap.containsKey(token.toUpperCase())) {
return symbolMap.get(token.toUpperCase());
}
return nameMap.get(token.toUpperCase());
}
Then in main
Element e = Element.fromString("H");
Element e2 = Element.fromString("Hydrogen");
System.out.println(e == e2); // <-- true
And if e were null then it isn't a valid symbol (or name).
If I have understood correctly, you want to go through the enums and see if any of the symbols match the user input. If not, print a message and try again. You had the right approach, but in the catch block you don't need to make a counter. Instead if we think through the design, you have break outer; if the input ever matches. So the end of the do-while loop will only be reached if there is no matching element. So if we just print a message at the end, this will accomplish our goal:
outer:
do {
Scanner reader = new Scanner(System.in);
String input = reader.nextLine().trim();
for (Element sy : Element.values()) {
if (sy.symbol.equalsIgnoreCase(input)) {
System.out.println("Element: " + sy + " (" + sy.symbol + ")" + "\nGroup: " + sy.group + "\nAtomic Mass: " + sy.weight);
reader.close();
break outer;
} else {
try {
cName = Element.valueOf(input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase());
System.out.println("Element: " + cName + " (" + cName.symbol + ")" + "\nGroup: " + cName.group + "\nAtomic Mass: " + cName.weight);
reader.close();
break outer;
} catch(IllegalArgumentException e) {
continue;
}
}
}
System.out.println("Error. No matching elements. Please try again.");
} while (true);
Sample Output:
Enter the name or symbol of an element in the periodic table.
No
Error. No matching elements. Please try again.
l
Error. No matching elements. Please try again.
He
Element: Helium (He)
Group: Noble Gas
Atomic Mass: 4.003
You complicate the code by mixing the search for the name and the search for the symbol. The search for the name does not need to be inside the for loop:
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("Enter the name or symbol of an element in the periodic table. ");
boolean found = false;
do {
String input = reader.nextLine().trim();
try {
cName = Element.valueOf(input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase());
System.out.println("Element: " + cName + " (" + cName.symbol + ")" + "\nGroup: " + cName.group + "\nAtomic Mass: " + cName.weight);
found = true;
} catch (IllegalArgumentException e) {
}
for (Element sy : Element.values()) {
if (sy.symbol.equalsIgnoreCase(input)) {
found = true;
System.out.println("Element: " + sy + " (" + sy.symbol + ")" + "\nGroup: " + sy.group + "\nAtomic Mass: " + sy.weight);
}
}
if (!found)
System.out.println("That name or symbol is not valid. Please try again. ");
} while (!found);
reader.close();
}
I want to create a program that handles the 3 possible exceptions that occur when dividing two ints, asking the user to correct the input if it triggers an exception. The code only executes if no exceptions are triggered. The following code works, but I feel it is too unoptimized. Is there no other way, other than while loops, to continuously check for exceptions?
import javax.swing.JOptionPane;
public class DivisionExceptions {
public int divide(int num, int den) {
return num/den;
}
public static void main(String[] args) {
int num = 0,
den = 0,
a = 0,
b = 0,
c = 0;
DivisionExceptions div = new DivisionExceptions();
while(a == 0) {
try {
num = Integer.parseInt(JOptionPane.showInputDialog("Introduce the first int"));
a++;
}
catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Error of type: " + e.getMessage() + ". Verify the information and try again.");
}
}
while (c == 0) {
b = 0;
while(b == 0) {
try {
den = Integer.parseInt(JOptionPane.showInputDialog("Introduce the second int"));
b++;
}
catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Error of type: " + e.getMessage() + ". Verify the information and try again.");
}
}
try {
JOptionPane.showMessageDialog(null, "Result of dividing: " + num + "/" + den + " is " + div.divide(num, den));
c++;
}
catch (ArithmeticException e) {
JOptionPane.showMessageDialog(null, "Error of type: " + e.getMessage() + ". Verify the information and try again.");
}
}
}
}
Could be simplified to:
public static void main(String[] args) {
int num = 0, den = 0;
DivisionExceptions div = new DivisionExceptions();
while(true) {
try {
num = Integer.parseInt(JOptionPane.showInputDialog("Introduce the first int"));
break;
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Error of type: " + e.getMessage() + ". Verify the information and try again.");
}
}
while (true) {
try {
den = Integer.parseInt(JOptionPane.showInputDialog("Introduce the second int"));
JOptionPane.showMessageDialog(null, "Result of dividing: " + num + "/" + den + " is " + div.divide(num, den));
break;
} catch (NumberFormatException | ArithmeticException e) {
JOptionPane.showMessageDialog(null, "Error of type: " + e.getMessage() + ". Verify the information and try again.");
}
}
}
~
Well your code could use some refactor.
public class DivisionExceptions {
public int divide(int num, int den) {
return num / den;
}
public static void main(String[] args) {
int num = 0,
den = 0,
a = 0,
b = 0,
c = 0;
DivisionExceptions div = new DivisionExceptions();
num = getNum(a, "Introduce the first int");
den = getNum(b, "Introduce the second int");
while (c == 0) {
try {
JOptionPane.showMessageDialog(null, "Result of dividing: " + num + "/" + den + " is " + div.divide(num, den));
c++;
} catch (ArithmeticException e) {
JOptionPane.showMessageDialog(null, "Error of type: " + e.getMessage() + ". Verify the information and try again.");
}
}
}
private static int getNum( int loopParam, String message) {
int num = 0;
while (loopParam == 0) {
try {
num = Integer.parseInt(JOptionPane.showInputDialog(message));
loopParam++;
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Error of type: " + e.getMessage() + ". Verify the information and try again.");
}
}
return num;
}
}
I also allow myself to extract den calculation from while(c==0) loop, because it always calculates same value but for n times, so you gain some optimilization here. If you can provide more information about why do you predefine all of your params as 0, than perhaps I could find some solution for that while(c==0) loop. If you use java 8 you could also extract your while loop to another method and give some Function as a param.
I'm working on a mortgage calculator in Java. I have to validate the data using try and catch blocks. I have done the rest of the program, but I can't figure out how to implement the try and catch blocks. Here's what the prompt is asking for:
"Write your own exceptions to validate your data by using try and catch blocks. For example loan amount cannot be a negative number and it should be between $5000 and $1,000,000."
Edit: Here's the try-catch block that finally worked. It needed to be placed in the actionPerformed method where the rest of my data is. I had another issue where the code kept throwing an exception for any amount that I entered until I figured out that I needed to place the for loop inside of the try block.
try
{
if((n1 < 5000) || (n1 > 1000000))
throw new Exception();
for (int i = 0; i < term[0] * 12; i++)
{
double interest_paid = n1 * (rate[0] / 12);
double principal_paid = tr1 - interest_paid;
n1 = n1 - principal_paid;
//Prints the results.
edit.append("\n " + (i+1) + " \t\t " + (two.format(interest_paid))
+ " \t\t " + (two.format(principal_paid)) + " \t\t "
+ (two.format(Math.abs(n1))));
}
}
catch (Exception e)
{
edit.setText("Please enter an amount between $5,000 and $1,000,000.");
mortText.setText("");
out.setText("");
}
Here's the try-catch block that finally worked. It needed to be placed in the actionPerformed method where the rest of my data is. I had another issue where the code kept throwing an exception for any amount that I entered until I figured out that I needed to place the for loop inside of the try block.
try
{
if((n1 < 5000) || (n1 > 1000000))
throw new Exception();
for (int i = 0; i < term[0] * 12; i++)
{
double interest_paid = n1 * (rate[0] / 12);
double principal_paid = tr1 - interest_paid;
n1 = n1 - principal_paid;
//Prints the results.
edit.append("\n " + (i+1) + " \t\t " + (two.format(interest_paid))
+ " \t\t " + (two.format(principal_paid)) + " \t\t "
+ (two.format(Math.abs(n1))));
}
}
catch (Exception e)
{
edit.setText("Please enter an amount between $5,000 and $1,000,000.");
mortText.setText("");
out.setText("");
}
In my program that turns roman numerals into arabic numbers I have run across the error
incompatible types: java.lang.String cannot be converted into int
Here is my code
if ( Character.isDigit(TextIO.peek()) ) {
int arabic = TextIO.getlnInt();
try {
RomanNumerals N = new RomanNumerals(arabic);
TextIO.putln(N.toInt() + " = " + N.toString());
}
catch (NumberFormatException e) {
System.out.println("Invalid input.");
System.out.println(e.getMessage());
}
}
else {
String roman = TextIO.getln();
try {
RomanNumerals N = new RomanNumerals(roman);
System.out.println(N.toString() + " = " + N.toInt());
}
catch (NumberFormatException e) {
System.out.println("Invalid input.");
System.out.println(e.getMessage());
}
}
I am using BlueJ and the error is being highlighted over "(roman)"
Guesswork here... but probably your class RomanNumerals does not have a constructor taking a string as an argument like
public RomanNumerals(String r) {
Thats why calling it that way:
RomanNumerals N = new RomanNumerals(roman);
Is not permitted.
I'm looking at TextIO.putln(N.toInt() + " = " + N.toString()); and imagining that N.toInt() returns an int and the compiler is confused when you try adding " = " to it.
Try TextIO.putln(Integer(N.toInt()).toString() + " = " + N.toString());.
I want to count the number of recursion steps and stop the recursion when a certain limit is reached.
Actually I am dealing with the Tower of Hanoi problem and I want to limit the number of slides that are performed to solve the problem. Here is my solution:
class HanoiNK{
public static void main(String args[]){
int n = 4;
int k = 5;
try{
slide(k, n, 'A', 'B', 'C');
}catch(Exception e){
System.out.println(e);
}
}
public static void slide(int counter, int height, char source,
char buffer, char destination) throws Exception{
if(counter > 0){
if(height == 1){
System.out.println("move "+ height +" from " +
source + " to " + destination);
}else{
counter--;
slide(counter, height - 1, source, destination, buffer);
System.out.println("move "+ hoehe +" from " +
source + " to " + destination);
counter--;
slide(counter, height - 1, buffer, source, destination);
}
}else{
throw new Exception("stop here");
}
}
}
Here is the live example: http://ideone.com/xeN4x
My problem is that I get
move 1 from A to B
move 2 from A to C
move 1 from B to C
move 3 from A to B
move 1 from C to A
move 2 from C to B
java.lang.Exception: stop
as output. But 5 and not 6 slides should be performed. Any ideas?
The problem is you are testing if counter is greater than or equal to one, but then decrementing it by two.
counter--;
// ...
counter--;
Here counter can go negative. You need to check for that.
Since you want to count the number of moves and not the recursion depth, you need to store the number of moves that were made in each step. Something like this:
public static int slide(int counter, int hoehe, char quelle, char ablage, char ziel)
throws Exception{
if (hoehe == 1) {
System.out.println("move "+ hoehe +" from " +
quelle + " to " + ziel);
if (--counter == 0) throw new Exception("hier stoppen");
} else {
counter = slide(counter, hoehe - 1, quelle, ziel, ablage);
System.out.println("move "+ hoehe +" from " +
quelle + " to " + ziel);
if (--counter == 0) throw new Exception("hier stoppen");
counter = slide(counter, hoehe - 1, ablage, quelle, ziel);
}
return counter;
}
Then, you obtain the expected result:
move 1 from A to B
move 2 from A to C
move 1 from B to C
move 3 from A to B
move 1 from C to A
java.lang.Exception: hier stoppen
Here is an sample method that will be recursively get called counter times
public void callMe(int counter){
if(counter == 1 ){
return;
}else{
callMe(--counter);
}
}
in your code there are counter--; twice so it won't met condition in many case
You have to test for your counter at every decrements like this:
public static void slide(int counter, int hoehe, char quelle,
char ablage, char ziel) throws Exception{
if(hoehe == 1){
System.out.println("move "+ hoehe +" from " +
quelle + " to " + ziel);
}else{
if (--counter == 0) throw new Exception("hier stoppen");
slide(counter, hoehe - 1, quelle, ziel, ablage);
System.out.println("move "+ hoehe +" from " +
quelle + " to " + ziel);
if (--counter == 0) throw new Exception("hier stoppen");
slide(counter, hoehe - 1, ablage, quelle, ziel);
}
}