0

I have the same problem as this question, I need to ensure that the user input is an integer and also consists of 7 digits, where as there I think instead an integer between 0 and 150 is needed:

I tried this

System.out.print("Please enter your ID without any spaces (7 digits): ");
        while (in.hasNextInt() == false || in.nextInt()/1000000 == 0 || in.nextInt()/10000000 > 0) 

// division with two integers by a million, if you had less than 7 digits would give zero
// division with two integers by ten million, if you had more than 7 digits would give you greater than zero
        {
            in.next();
            System.out.print("Please enter your ID without any spaces (7 digits): ");
        }
        student_ID = in.nextInt();


// Sample Output:

Please enter your ID without any spaces (7 digits): 123 

and then it just stops there even if I have other print statements following after. It works for the in.hasNextInt() part alone if I just have that in brackets for while, however I don't know how to add more conditions to the while loop (prompting the user until they input a 7-digit integer), I tried with a do loop as well, without success.

p.s. I know there's no int in front of student_ID I declared it an integer variable higher up in my code so no need to worry there :)

1 Answer 1

1

You made many logical errors in your program. Lets make a line by line check. After prompting the user to input a 7-digit number. You go in the while loop.

while (in.hasNextInt() == false || in.nextInt()/1000000 == 0 || in.nextInt()/10000000 > 0)

Suppose you type 123 and press enter. This 123 will be consumed by the scanner object in. Right now the in only consists of a single token 123. Now here is what happens.

The first condition in the while loop text expression is in.hasNextInt() == false is checked. It will evaluate to false since in does have an int as next token. However, in will still contain 23. According to docs.oracle.com:

public boolean hasNextInt(int radix)

Returns true if the next token in this scanner's input can be interpreted as an int value in the specified radix using the nextInt() method. The scanner does not advance past any input.

Now the control passes to the next condition in the while loop text expression. in.nextInt()/1000000. Here an 23 will be scanned as an int and will be returned. So your condition will evaluate to true. The next condition in the while loop test expression is not checked since you have used a short circuit logical operator. Here is a link on short circuit logical operators for more information.

https://www.geeksforgeeks.org/short-circuiting-in-java-with-examples/#:~:text=In%20Java%20logical%20operators%2C%20if,is%20known%20as%20Short%2Dcircuit.&text=If%20there%20is%20an%20expression,evaluated%20and%20false%20is%20returned.

Your program control will pass inside the while loop now. Here the first statement is in.next(). However, there are no tokens available inside 'in. So it will stop there waiting for user input. This explains your statement.

then it just stops there even if I have other print statements following after

To make things worse, in.next() will accept any input valid. So you could even input abc and the loop will continue. This is opposite to what you want.

public String next()

Finds and returns the next complete token from this scanner. A complete token is preceded and followed by input that matches the delimiter pattern. This method may block while waiting for input to scan, even if a previous invocation of hasNext() returned true.

Here is a link for more information on scanner class in java:

https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html

There are more potential errors in your program which I can not share in this answer as it make it quite long. However, I will provide a code which is working according to your needs:

do
{
    System.out.print("Please enter your ID without any spaces (7 digits): ");
    // division with two integers by a million, if you had less than 7 digits would give zero
    // division with two integers by ten million, if you had more than 7 digits would give you greater than zero
        
    if (in.hasNextInt()) number = in.nextInt();
    else in.next();
}
while (number/1000000 == 0 || number/10000000 > 0);

The program consists of a simple do-while loop. The first statement in the loop prompts the user to input his UID (7 digit number). Suppose the user typed 23 and pressed enter. This input is then stored somewhere for use by the scanner object in. Lets call this space input buffer. Right now it consists of:

23\n

\n stands for newline feed. In the loop, the next statement is:

in.hasNextInt() number = in.nextInt();

The if condition is true since the input buffer does have an int, that is, 23 stored in it. The statement following the if extracts 23 from the input buffer, skips over \n and stores the extracted number in number. Then the control passes to the test condition of the do-while where since the number does not pass the given constraints, the loop is started again. Right now the input buffer consists of:

Its empty. Now suppose this time the user inputted abc and pressed enter. The input buffer is updated to:

abc\n

The program control is passed to the if condition again where it evaluates to false since input buffer does not contain an int. We have to remove abc from the input buffer. If we do not do so, then each call to if condition in the do-while loop will evaluate to false and number still contains 23 so the final test condition of the loop will always be true resulting in an infinite loop.

That is why the in.next() in the else part is necessary:

else in.next();

Since the if condition is false, the program control moves to the else part where a call to in.next() extracts abc from the input buffer, skips over \n and does not store it anywhere. It empties the input buffer of any non-int part.

Please do note in this implementation if you do not provide any input and keep on pressing enter. This prompt message Please enter your ID without any spaces (7 digits): will not be displayed as you need to provide an input of at least one character(excluding delimiter) to the scanner.

Also even though there is a space called input buffer. Its working is not as simple as I have explained. This approach does work in simple programs. However, in complex programs a better approach should be adopted.

The scanner does not skip over \n when using nextInt() or next(). Thinking that they do while writing other programs might result in different errors. I have used this to keep my explanation simple. Do visit the scanner link I mentioned above for the precise working of scanner methods.

Sign up to request clarification or add additional context in comments.

7 Comments

thank you so much! Do I have to define number ? I defined number as int number = 0; to enter the loop?
@nolemonnomelon Yes you do have to declare int number and initialize it to 0. I forgot to mention it.
thank you so much once again, I included || number < 0 inside the while to also account for possible negative number entries, I will certainly take my time to digest everything you have written, I'm reading Java for Everyone, do you suggest going straight to docs.oracle.com? because there I don't see a way to do the line by line analysis you did with just my text
If you are a beginner, you might face some trouble in understanding oracle docs. Do visit it thought if you are facing any problems. If you cannot understand it, check other trusted sources like Stack Overflow, Geek for geeks, etc. In this way you will slowly get used to it, it will help you in future in many ways.
@nolemonnomelon I have updated my answer. Please also read the updated end part.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.