zerodeficit
zerodeficit

Reputation: 33

Java: console skipping input

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.

Upvotes: 3

Views: 3840

Answers (4)

Yogendra Singh
Yogendra Singh

Reputation: 34367

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

Upvotes: 4

Rohit Jain
Rohit Jain

Reputation: 213261

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.

Upvotes: 1

Andrew Backes
Andrew Backes

Reputation: 1904

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.

Upvotes: 1

tjg184
tjg184

Reputation: 4676

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

Upvotes: 0

Related Questions