"Exception in thread" and more - java

import java.util.Scanner;
public class Power1Eng {
public static void main(String[] args) {
double x, prod = 1;
int n;
String s;
Scanner input = new Scanner(System.in);
System.out.print("This program prints x(x is a real number) raised to the power of n(n is an integer).\n");
outer_loop:
while (true) {
System.out.print("Input x and n: ");
x = input.nextDouble();
n = input.nextInt();
for (int i = 1; i <= n; i++) {
prod *= x;
}
System.out.printf("%.1f raised to the power of %d is %.4f. Do you want to continue?(Y/N) ", x, n, prod);
s = input.nextLine();
if (s.charAt(0) == 'Y')
continue;
else if (s.charAt(0) == 'N')
break;
else {
inner_loop:
while (true) {
System.out.print("Wrong input. Do you want to continue?(Y/N) ");
s = input.nextLine();
if (s.charAt(0) == 'Y')
continue outer_loop;
else if (s.charAt(0) == 'N')
break outer_loop;
else
continue inner_loop;
}
}
}
}
}
There was only trivial logical error when I used just next() method, but when I changed
next() method to nextLine() method, this error shows.
How can I fix this problem?

There are two problems. The first is that your string could be empty, and then fetching the first character will give an exception.
if (s.charAt(0) == 'Y') // This will throw if is empty.
Either test the length of the string to see if there is at least one character, or just use String.startsWith instead of charAt:
if (s.startsWith('Y'))
The second problem is that you entered a new line after your first input, and nextLine reads up to the next new line character only.

You could check for an initial character count, to make sure there are the correct number of characters that you expect. i.e:
while (true)
{
// ... some code ...
if (s.length() < 1)
{
continue;
}
// ... some code ...
}
This way, you wouldn't even have to continue running the rest of the code, which if the code base were larger, would help to optimize performance.

The "red text" that you see in the console is an indication of text being sent to standard error. In this case, it is an indication that your program has crashed.
The main problem you are encountering is with this logic:
System.out.print("Input x and n: ");
x = input.nextDouble();
n = input.nextInt();
for (int i = 1; i <= n; i++) {
prod *= x;
}
System.out.printf("%.1f raised to the power of %d is %.4f. Do you want to continue?(Y/N) ", x, n, prod);
s = input.nextLine();
Suppose the user input is:
2.1 4(enter)
input.nextDouble() will take 2.1, leaving 4(enter) on the standard input stream.
input.nextInt() will take 4, leaving (enter) on the standard input stream.
input.nextLine() will take "" (empty string), finally clearing the (enter) from the initial user input of x and n.

Related

How do I prevent an error message from repeating in Java?

I'm trying to write a program to calculate factorial but I can't figure out why the Error message displays twice if I enter a letter instead of an integer.
I feel like the issue has to do with Line 29 c = sc.next().charAt(0);, but am not sure how to fix it. Any help is appreciated.
My program:
public class Factorials {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char c = 'Y';
int num = 0;
do
{
System.out.print("Enter a number to calculate its factorial: ");
while (!sc.hasNextInt()) {
System.out.println("Invalid Entry - Enter only Integers! Try Again: ");
sc.nextLine();
}
int result = 1;
num = sc.nextInt();
for(int i = 1; i <= num; i++) {
result = result * i;
}
System.out.println("The factorial of " + num + " is: " + result);
System.out.println("Do you wish to continue? Y/N: ");
c = sc.next().charAt(0);
}while(c == 'y' || c == 'Y');
sc.close();
}
}
Simple fix: Change the sc.nextLine(); in your code to a sc.next() and you should be good to go. This error occurs because .nextLine() considers the enter/return key as a separate character, while .next() doesn't. (The enter key when you press it after entering either 'y' or 'n': if you try it, the error message doesn't print twice if you enter a letter the first time you run the program).
Side note: You probably want it to be a .print(/*invalid input sentence*/) instead of a .println() to go along with how you take in your other number values.
Otherwise, you're good!
Finds and returns the next complete token from this scanner.
A complete token is preceded and followed by input that matches
the delimiter pattern
As jdk doc shows, the 'sc.next' method will return when it reaches space, enter or return. So when you enter 'y' with enter, the enter character is still in buffer. You can assign sc.nextLine to a variable, like
String str = sc.nextLine();
System.out.println(str);
You can see the enter character and your input character.
Both #TheSj and #Lahiru Danushka answer could solve this problem.
add sc.nextLine(); after c = sc.next().charAt(0);

Replacing a String statment that's being used by a constructor

So I'm working on a project to count the number of vowels and consonants of a desired string. I've got almost everything working, but I can't seem to get the option to replace the string with a new one to work properly. I think it's a problem with having the new choice be applied to the Driver construct but I can't seem to figure out a way to do that without breaking the program.
import java.util.*;
public class Driver{
private String entry;
int vowels = 0;
int cons = 0;
public Driver(String input){
entry = input;
this.count();
}
public boolean isVowel(char x){
return (x == 'A' || x == 'E' || x == 'I' || x == 'O' || x == 'U' ||
x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u');
}
public boolean isConsonant(char x){
return (((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z')) && !isVowel(x));}
public int getVowels(){
return vowels;
}
public int getConsonants(){
return cons;
}
public void count(){
int l = entry.length();
for(int i = 0; i < l; i++){
if(this.isVowel(entry.charAt(i))){
vowels++;
}else{
if(this.isConsonant(entry.charAt(i))){
cons++;
}
}
}
}
static Scanner kb = new Scanner(System.in);
public static void main(String[] args){
int choice; //Choice from menu
int vowels = 0; //# of vowels in entry
int cons = 0; //# of consonants in entry
String entry; //User's input
System.out.print("Enter a string:");
entry = kb.nextLine();
do{
Driver sentence = new Driver(entry);
System.out.println("Enter a number");
System.out.println("1. Count the number of vowels in the string");
System.out.println("2. Count the number of consonants in the string");
System.out.println("3. Count both the vowels and consonants in the string");
System.out.println("4. Enter another string");
System.out.println("5. Exit the program:");
choice = kb.nextInt();
switch(choice){
case 1:
System.out.println("Vowels: " + sentence.getVowels());
break;
case 2:
System.out.println("Consonants: " + sentence.getConsonants());
break;
case 3:;
System.out.println("Vowels: " + sentence.getVowels() + "\nConsonants: " + sentence.getConsonants());
break;
case 4:
System.out.print("Enter a string:");
entry = kb.nextLine();
//Driver sentence = new Driver(entry);
break;
default:
System.out.println("Please enter a value input: ");
}
}while(choice != 5);
}
}
You should have the Driver Class on its own (without the main() method).
Then create another Class that will be your startup Class which will contain the main() method). For the sake of argument let's call it VowelsAndConsonants.
The problem that's causing all the grief is your keyboard entry of 1 to 5 for the Console menu. You are using the Scanner.nextInt() method which is okay as long as you know that the whatever is entered is not all consumed and remains within the Scanner buffer and this is because the Scanner.nextInt() method doesn’t read and consume the line separator that is applied when the Enter Key is hit. So, when Scanner.nextLine() is used as the next Scanner method the first thing it gets hold of is that line separator that's held within the Scanner buffer which in turn is just like hitting the Enter key and therefore it skips what was typed. On the other hand the Scanner.nextLine() method does read in and consume the line separator. One way to get around this problem is to add (in your case) kb.nextLine(); directly after the choice = kb.nextInt(); code line. This forces the line separator to be consumed and empties the buffer. In essence the menu would then look something like this:
Driver sentence = new Driver(entry);
do {
System.out.println("Enter a Menu choice (1 to 5): ");
System.out.println("1. Count the number of vowels in the string");
System.out.println("2. Count the number of consonants in the string");
System.out.println("3. Count both the vowels and consonants in the string");
System.out.println("4. Enter another string");
System.out.println("5. Exit the program:");
choice = kb.nextInt();
kb.nextLine(); // Consume
..... the rest of your do/while code .....
}
EDIT: Based on your Question in Comment: "I'm curious as to why
there is a difference in how the line separator is dealt with tho. Is
this just something that is in Java, or is there a reason that it
isn't consumed from nextInt()?"
The Scanner Class is quite involved. It is by design that the nextInt() does this since Scanner can work based on tokens. You can use nextInt() to accept multiple numbers on a single input using (for example) a whitespace delimiter and then with the Scanner.hasNextInt() or Scanner.hasNext() methods in conjuction with the Scanner.nextInt() you can individually acquire each value, for example:
Scanner kb = new Scanner(System.in).useDelimiter(" *");
System.out.println("Enter numbers delimited with a white-space: ");
while (kb.hasNextInt()) {
int x = kb.nextInt();
System.out.println(x);
}
If you were to run this code and at the prompt enter on one line:
2 4 6 8 10
(note the whitespace between numbers) you will see a display within the Console window of:
2
4
6
8
10
Through each iteration of the while loop x would equal the next integer token from the line of numbers entered. This sort of thing however is best suited for reading numbers from a text file which Scanner can do as well. Read up on the Scanner Class.

Validate, inform if invalid, return to loop

I am having problems with this section of my code. The program asks for a couple inputs (name, ID, grade, etc.) and will then print the results back.
I decided to break away from the tutorial and have now been smacking my head on a proverbial wall -
Pseudocode for what I want here:
Ask user for grade between 9 and 12
If input is less than 9 or greater than 12, return failed message and -return to loop-
If input acceptable, continue to next question.
Current code is as follows:
do {
System.out.print("Grade (9-12): ");
while (!keyboard.hasNextInt()) {
System.out.printf("message saying you're wrong");
keyboard.next();
}
userGrade = keyboard.nextInt();
} while (userGrade >= 9 || userGrade <= 12);
Try with something like this:
boolean correct = true;
do {
System.out.print("Grade (9-12): ");
userGrade = keyboard.nextInt();
if (userGrade < 9 || userGrade > 12) {
correct = false;
System.out.println("message saying you're wrong");
} else {
correct = true;
}
} while (!correct);
I think the problem is on the logic...
Change
while (userGrade >= 9 || userGrade <= 12);
to:
while (userGrade >= 9 && userGrade <= 12);
The || accept anything higher and equal to 9 and below and equal to 12. The two condition make finally that any integer will be true in the condition.
You can split your task in smaller ones. For instance create helper methods which
will read from Scanner until it will find integer which then will be returned
public static int getInt(Scanner scanner, String errorMessage){
while (!scanner.hasNextInt()) {
System.out.println(errorMessage);
scanner.nextLine();
}
return scanner.nextInt();
}
or will check if number is in range (but that is just for readability)
public static boolean isInRange(int x, int start, int end){
return start <= x && x <= end;
}
So with this methods your code can look like
Scanner scanner = new Scanner(System.in);
int x;
System.out.println("Please enter a number in range 9-12:");
do {
x = getInt(scanner, "I said number. Please try again: ");
if (!isInRange(x, 9, 12))
System.out.println("I said number in range 9-12. Please try again: ");
} while (!isInRange(x, 9, 12));
System.out.println("your number is: " + x);

The program do not stop(to receive string) at expected point

import java.util.Scanner;
public class Power1Eng {
public static void main(String[] args) {
double x, prod = 1;
int n;
String s;
Scanner input = new Scanner(System.in);
System.out.print("This program prints x(x is a real number) raised to the power of n(n is an integer).\n");
outer_loop:
while (true) {
System.out.print("Input x and n: ");
x = input.nextDouble();
n = input.nextInt();
for (int i = 1; i <= n; i++) {
prod *= x;
}
System.out.printf("%.1f raised to the power of %d is %.4f. Do you want to continue?(Y/N) ", x, n, prod);
s = input.nextLine();
if (s.equals("Y"))
continue;
else if (s.equals("N"))
break;
else {
inner_loop:
while (true) {
System.out.print("Wrong input. Do you want to continue?(Y/N) ");
s = input.nextLine();
if (s.equals("Y"))
continue outer_loop;
else if (s.equals("N"))
break outer_loop;
else
continue inner_loop;
}
}
}
}
}
Look at the Console. In the third line, I expected the program prints until the first 'Do you want to continue?(Y/N)', but it also prints 'Wrong input. Do you want to continue?(Y/N)'. How can I fix this problem?
When you do the nextInt and nextDouble, it doesn't clear the (empty) rest of the line.
You need to call nextLine after reading these values to clear the rest of the line.
System.out.printf("%.1f raised to the power of %d is %.4f. Do you want to continue?(Y/N) \n", x, n, prod);
s = input.next();
That will solve your problem and also do not use labels.
Should I avoid using Java Label Statements?
People who get to maintain that code will find you.

Easier way to guarantee integer input through Scanner?

For a program I am writing, I need to ask a user for an integer between 1 and 8. I've tried multiple (cleaner) ways of doing this but none of them worked, so I'm left with this:
int x = 0;
while (x < 1 || x > 8)
{
System.out.print("Please enter integer (1-8): ");
try
{
x = Integer.parseInt(inputScanner.next());
}
catch(NumberFormatException e)
{
x = 0;
}
}
Where inputScanner is a Scanner. Surely there is a better way?
Scanner does regular expressions, right? Why not check if it matches "^[1-8]$" first?
Using the nextInt() is already an improvement compare to simply using the next() method. And before that, you can use the hasNextInt() to avoid haing all this bunch of useless exceptions.
Resulting in something like this:
int x = 0;
do {
System.out.print("Please...");
if(scanner.hasNextInt()) x = scanner.nextInt();
else scanner.next();
} while (x < 1 || x > 8);
I had to do a graphic interface calculator (works only with Integers), and the problem was, that
the Tests didn't allow any Exceptions to be thrown if the input wasn't
Integer. So I couldn't use
try { int x = Integer.parseInt(input)} catch (Exception e) {dosomethingelse}
Because Java programs generally treat an input to a JTextField as a String
I used this:
if (input.matches("[1-9][0-9]*"){ // String.matches() returns boolean
goodforyou
} else {
dosomethingelse
}
// this checks if the input's (type String) character sequence matches
// the given parameter. The [1-9] means that the first char is a Digit
// between 1 and 9 (because the input should be an Integer can't be 0)
// the * after [0-9] means that after the first char there can be 0 - infinity
// characters between digits 0-9
hope this helps :)
You could try something like this:
Scanner cin = new Scanner(System.in);
int s = 0;
boolean v = false;
while(!v){
System.out.print("Input an integer >= 1: ");
try {
s = cin.nextInt();
if(s >= 1) v = true;
else System.out.println("Please input an integer value >= 1.");
}
catch(InputMismatchException e) {
System.out.println("Caught: InputMismatchException -- Please input an integer value >= 1. ");
cin.next();
}
}
Apache Commons is your friend. See NumberUtils.toInt(String, int)
String input;
int number;
while (inputScanner.hasNextLine())
{
input = inputScanner.nextLine();
if (input.equals("quit")) { System.exit(0); }
else
{
//If you don't want to put your code in here, make an event handler
//that gets called from this spot with the input passed in
try
{
number = Integer.parseInt(input);
if ((number < 1) || (number > 8))
{ System.out.print("Please choose 1-8: "); }
else { /* Do stuff */ }
}
catch (NumberFormatException e) { number = 0; }
}
}
I always like to pull in the full string so you can be sure that the user pushed the Enter button. If you just use inputScanner.nextInt() you can put two ints on a line and it will pull in one, then the other.
Example code:
int x;
Scanner in = new Scanner(System.in);
System.out.println("Enter integer value: ");
x = in.nextInt();
An array can also be used to store the integer.

Categories

Resources