Java: console skipping input - java

I'm trying to parse a char from console input using in.nextLine() and from there take charAt(0). My problem is after asking the user to enter a string to perform the in.nextLine() on, it skips the input and yields an error due to trying to get the first character of a null string.
System.out.print("Select an operator (+, -, *, /), 'c' or 'C' to clear, or 'q' to quit: ");
String temp = in.nextLine();
char tempOperator = temp.charAt(0);
the error is
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.lang.String.charAt(Unknown Source)
full program is available here
General comments and suggestions always welcome.
Thanks in advance.

When you do cValue = in.nextDouble();, it reads the next token(full value) and parses it to double. If the return key was pressed at this time, \n is the next token in the buffer to read.
When you do: String temp = in.nextLine();, it reads the \n from the buffer of the previous enter and charAt(0) fails as it has read only empty("") string.
To overcome the issue, either skip the previous buffer by adding an addition in.nextLine(), add \n \r as skip pattern as below (this is the pattern defined in Scanner.class as LINE_SEPARATOR_PATTERN):
in.skip("\r\n|[\n\r\u2028\u2029\u0085]");
or put a small while loop as below:
String temp = "";
while((temp.length() < 0){
temp = in.nextLine();
}

One thing you might consider is instead of doing this:
String temp = in.nextLine();
Do this:
String temp = in.next();
That of course is assuming that you only want a single character from the user input, which it looks like that is all you are asking the user for. This will get rid of the exception you are receiving. However, you may want to read the whole line first to see what the length is, if you would like to throw an error when the user types more than one character.

Well, the problem is in the line in.nextDouble().
Scanner#nextDouble reads the next token from the user as double. So, when you pass a value 4.5 as input, then the nextDouble just reads the token 4.5 and skips the linefeed after that input that user have entered. Now this linefeed(Since this is a new line), will be regarded as input for the next Scanner.nextLine. And hence your in.nextLine after in.nextDouble is reading the newline left over by the previous in.nextDouble.
So, the workaround is the same that #tjg184 has pointed out in his answer. Add an empty in.nextLine after in.nextDouble that will read that newline left over. So, that your coming in.nextLine reads the input actually passed.
cValue = in.nextDouble();
in.nextLine(); // Add this before your `while` which will read your `newline`
while (true) {
//continue;
}
Whereas, Scanner.nextLine reads the complete input till the newline. So, it will not leave any newline to be read by the next read by user.
Although this answer was not needed, as the #tjg184's answer does the same. I just added it to give a better explanation of what exactly is happening.

Looking at your program, it's because of String temp = in.nextLine();. When the user hits the "Enter" key, it essentially is skipping this statement since the user typed hit "Enter". Try the following. Note, I only added the following line String enter = in.nextLine();
import java.util.Scanner;
public class Calculator
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
char operator = 'z'; //initialize operator
double cValue; //current value
double rhValue; //right hand value
boolean cont = true;
System.out.print("Enter starting value: ");
cValue = in.nextDouble();
// disregard the "Enter" key
String enter = in.nextLine();
while(true)
{
System.out.print("Select an operator (+, -, *, /), 'c' or 'C' to clear, or 'q' to quit: ");
String temp = in.nextLine();
char tempOperator = temp.charAt(0);
if (tempOperator == 'c' || tempOperator == 'C')
{
cValue = 0.0;
System.out.println("Current value is: " + cValue);
System.out.println();
}
else if(tempOperator == 'q')
{
System.out.println("Final result: " + cValue);
System.exit(1);
}
else if(tempOperator == '+' || tempOperator == '-' || tempOperator == '*' || tempOperator == '/')
{
operator = tempOperator;
break;
}
else
throw new IllegalArgumentException("operator not valid");
}
System.out.println("Enter a right hand value (type double): ");
rhValue = in.nextDouble();
System.out.println("Math expression: answer " + operator + "= " + rhValue);
switch(operator)
{
case '+': cValue =+ rhValue;
break;
case '-': cValue =- rhValue;
break;
case '*': cValue = cValue * rhValue;
break;
case '/': cValue = cValue / rhValue;
break;
}
System.out.println("Current value is: " + cValue);
}
}

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

Last entered char to lower case or upper case

I have a code. Input character, program stops when I input full stop (.).
So, i want to change my last entered char to lower case if user input upper case, or upper case if user input lower case. So my problem is how to change upper case to lower or lower to upper. I dont know how to find last index.
Example:[g j g k . K] or [k j f G . g]
Scanner input = new Scanner(System.in);
String character = input.nextLine();
while (true) {
String character1 = input.nextLine();
if (character1.equals(".")) {
break;
So, i just made that my progaram stop when user input full stop, and i dont know how to change last entered char to lower or upper case!
String character ="C".toLowerCase();
if you mean String and not char...
Probably you try change input but it is not possible. You have to print every character on output.
You can try something like this:
Scanner input = new Scanner(System.in);
Char lastChar = '';
while (true) {
String character1 = input.nextLine();
if (character1.equals(".")) {
if(isBig(lastChar)) {
print(lowerCase(lastChar));
} else {
print(upperCase(lastChar));
}
break;
}
print(lastChar);
lastChar = character1;
}
Build around the following.
The first two check if the character is upper case or lower case. Next two convert two upper case and lower case respectively.
https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#isUpperCase(char)
https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#isLowerCase(char)
https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#toUpperCase(char)
https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#toLowerCase(char)
So, it would go something like this. It only converts the last character if it is a letter. If you need the last letter and not the last character, you can easily modify it.
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter("");
List<Character> characters = new ArrayList<>();
while(true){
String token = scanner.next();
if( token.equals(".") ){
break;
}
characters.add(token.charAt(0));
}
for( int i = 0 ; i < characters.size() - 1 ; i++){
System.out.print(characters.get(i));
}
Character lastCharacter = characters.get( characters.size() - 1 );
if( Character.isUpperCase( lastCharacter ) ) {
lastCharacter = Character.toLowerCase(lastCharacter);
}else if( Character.isLowerCase( lastCharacter )) {
lastCharacter = Character.toUpperCase(lastCharacter);
}
System.out.println( lastCharacter );

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.

How do I use hasNext() along with Scanner in a while loop in Java?

I have only a few weeks of experience in Java and I'm having trouble with an assignment I was given in my Intro to Java class. The assignment is write a program that allows the user to input a letter and determines whether the letter is a vowel or a consonant. The code I wrote for that works fine, but when I try to add in a while loop so the user can enter as many letters as they'd like, the program no longer works. My professor says the loop should continue until reaching EOF, and I followed the outline he gave but I'm still having trouble. This is the entire code:
import java.util.Scanner;
public class Vowel
{
public static void main(String [] args)
{
Scanner in = new Scanner(System.in);
String w;
while(in.hasNext())
{
w = in.next();
System.out.print("Enter a letter: ");
char letter = in.nextLine().charAt(0);
int ascii;
ascii =((int) letter);
Boolean valid = true;
if (ascii < 65 || ((ascii > 90) && (ascii < 97)) || ascii > 122)
{
System.out.println(letter + " is an invalid input");
valid = false;
}
else if(valid)
{
System.out.print(letter + " is a ");
switch (ascii)
{
case 'a' :
case 'A' : System.out.println("vowel");
break;
case 'e' :
case 'E' : System.out.println("vowel");
break;
case 'i' :
case 'I' : System.out.println("vowel");
break;
case 'o' :
case 'O' : System.out.println("vowel");
break;
case 'u' :
case 'U' : System.out.println("vowel");
break;
default : System.out.println("consonant");
}
}
}
}
}
When I run the code as is, the console just stays blank and if I type anything in (just trying to get it to do something), I get an error that says "Exception in thread "main" java.lang.StringOutOfBoundsException: String index out of range: 0."
The code works without the while loop and it also works with a while loop using a counter, so I know my mistake has something to do with the hasNext(). If anyone could point me in the right direction, it would be greatly appreciated! Thank you :)
You are ignoring w and reading another line, but you haven't checked that there is a line to read or that the line you read isn't empty. You could do so with something like
if (in.hasNextLine()) { // <-- check if there is a line.
String line = in.nextLine(); // <-- read the line.
if (!line.isEmpty()) { // <-- make sure there is at least one character.
char letter = line.charAt(0); // <-- get the first character.

For loop does not execute the first command after 2nd time

Here is my code:
import java.util.Scanner;
public class BankAccount1
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
char pickup;
char size;
char type;
String name;
double cost=0.0;
int i;
for (i=0; i<2; i++)
{
System.out.println("What is your name?");
name = input.nextLine();
System.out.println("size of pizza: ");
size = input.next().charAt(0);
System.out.println("type of pizza: ");
type = input.next().charAt(0);
System.out.println("pick up or delivery?");
pickup = input.next().charAt(0);
if(size == 'S' || type == 'V') {cost = 10.0;}
else if(size == 'M' || type == 'V') {cost = 12.25;}
else if(size == 'L' || type == 'V') {cost = 14.50;}
else if(size == 'S' || type == 'C') {cost = 7.0;}
else if(size == 'M' || type == 'C') {cost = 8.0;}
else if(size == 'L' || type == 'C') {cost = 9.0;}
if(pickup == 'D'){
cost=cost+1.50;
System.out.println("Name: "+name+". Your cost is: "+cost);}
else {
System.out.println("Name: "+name+". Your cost is: "+cost);}
}
}
}
I have a for loop in my code, and it asks the name, size, type and pickup. The first time it is run, it asks all fields to be entered, but for the 2nd time, the name field does not let me input the name for some reason, it prints the "What is your name?" but it does not let me enter the name...? can someone tell me why?
Thanks.
this is what it looks like: http://i.stack.imgur.com/eb1BA.jpg
Due to the fact that
input.next()
does not consume newline characters, these get passed passed back to your loop and does not allow a value to be entered. You would need to add:
for (i = 0; i < 2; i++) {
// existing input.next() statements in here
...
input.nextLine();
}
at the end of the for loop to fix.
When you use a Scanner with System.in, data isn't read from System.in until a newline (you've hit Enter). So what you actually have in the Scanner's buffer is:
Jake\nL\nV\nD\n
The key here is that D doesn't get sent to the Scanner's buffer until you've pressed enter. That's why there's that \n at the end. Normally, when you're calling input.next(), that previous stray newline gets gobbled up. But when you call input.nextLine() the second/third time around the for loop, it's reading that stray trailing newline:
here ----v
Jake\nL\nV\nD\n
So you get a blank line, essentially reading everything between the D and \n, which is nothing.
You need to call nextLine() each time and call charAt(0) on the resulting String.
Replace your input.next()'s with input.nextLine()'s. That should fix it.
I had a similar problem, and this helped me.
declare this outside the loop:
boolean ranOnce=false;
then inside the loop declare this
if(!ranOnce){ranOnce=true;String s=input.nextLine();}

Categories

Resources