0

i've got some problems in java with putting scanner after a output, in a while loop. the scanner scans which method to go and then when it comes back to the start of the loop reset the variable.

i've already tried this,and failed to find any understandable solution (im really new to java, and it is hard for me), or to solve it my self. here is the full code (i know the code is not so efficient):

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        int con=1;
        System.out.println("Hey!,welcome to my games!");
        Scanner scanner=new Scanner(System.in);
        String game;
        while(con==1) 
        {
            System.out.println("Here Some games i have(Enter the text for the one you want):\nto stop=0\n1)calculator=1\n2)!Soon! Random numbers");
            game=scanner.nextLine();
            calculator();
            scanner.reset();
            System.out.println(game);
//          if(game.equals("0")) {
//              con=0;
//          }
//          else if(game.equals("1")) {

//              System.out.println("Welcome Back!");
//          }
//          else {
//              System.out.println("There is a mistake in your text");
//          }

        }
    scanner.close();
    }
    static void calculator() {
        int num1,num2,con=1,stop=1;
        String op,ad="add",su="sub",mul="multi",di="div";
        Scanner af=new Scanner(System.in);  
        while (con==1) {
            stop=1;
            System.out.println("Write number 1");
            num1=af.nextInt();
            System.out.println("Write number 2");
            num2=af.nextInt();
            System.out.println("Write an operation (one of these):\nAddition=add\nSubtraction=sub\nMultiplication=multi\nDivision=div");
            op=af.next();
            op=op.toLowerCase();
            int minus=num1-num2;
            int plus=num1+num2;
            if(op.equals(ad)) {
                System.out.println("The Operation is:Addition\n"+num1+"+"+num2+"="+plus);
            }
            else if(op.equals(su)){
                System.out.println("The Operation is:Subtraction\n"+num1+"-"+num2+"=" + minus);
            }
            else if(op.equals(mul)){
                System.out.println("The Operation is:Multiplication\n"+num1+"*"+num2+"="+num1*num2);
            }
            else if(op.equals(di)){
                System.out.println("The Operation is:Division\n"+num1+"/"+num2+"="+num1/num2);
            }
            else {
                System.out.println("Um,Did you make a mistake in your text?\nDo you want the calculator again?");
                String yn=af.next();
                yn=yn.toLowerCase();
                if (yn.equals("yes") || yn.equals("yep")) {
                    stop=0;
            }
            }
            if (stop==1) {
                con=0;
            }
            }
    af.close();
    }
}

as you can see, i tried myself to solve it and even put a comment on some of the code, but when it runs to the method and comes back, it fails because the scanner thinks there is something to scan before i wrote something. here is the exception-

Exception in thread "main" java.util.NoSuchElementException
    at java.base/java.util.Scanner.throwFor(Scanner.java:937)
    at java.base/java.util.Scanner.next(Scanner.java:1478)
    at Main.main(Main.java:12)
Infinite
  • 23
  • 4
  • You should not open and close the Scanner each time in the loop. Open it before the loop, run your loop, then after the loop close the Scanner. – takendarkk Apr 02 '20 at 13:28
  • yes you are right, i tried to put the new scanner and to close him out of the while loop,for some reason it still put the same exception – Infinite Apr 02 '20 at 13:35
  • Use `nextLine()` instead of `next()`. `nextLine()` will read the entire input line. `next()` will only read the next token, which can lead to it leaving unwanted information in the Scanner. – Tim Hunter Apr 02 '20 at 13:41
  • See [this thread](https://stackoverflow.com/questions/22458575/whats-the-difference-between-next-and-nextline-methods-from-scanner-class) for more information. – Tim Hunter Apr 02 '20 at 13:43
  • Hi, i saw the thread and i can understand the use of this, i tried it too on my program and there is still the same problem. i am pretty sure it for some reason because the scanner doesn't resets the value of "game" – Infinite Apr 02 '20 at 13:54
  • See here https://stackoverflow.com/a/13042296/13163131 – humble_barnacle Apr 15 '21 at 18:10
  • Apparently, closing the scanner object in a function call (in the calculator method here) causes the Inputstream to close and hence the issue – humble_barnacle Apr 15 '21 at 18:11

2 Answers2

0
  1. You need a mechanism to loop-back (i.e. ask the user to enter the data again) in case of an invalid entry. One of the most common ways is to use do-while loop which guarantees to execute its body at least once. Check this tutorial to learn more about it.
  2. Use Scanner::nextLine instead of Scanner::next, Scanner::nextInt etc. because they do not consume the newline character, created by hitting Enter key, from the input. Check this discussion to learn more about it.
  3. Last but not least, never close a Scanner for System.in as it also closes System.in and there is no way to open it again without restarting the JVM. Note: If you are using Scanner to scan a File, make sure to close it in order to release the resource.

Demo:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        int option;
        boolean valid;
        Scanner input2 = new Scanner(System.in);
        do {
            valid = true;
            System.out.println("Choose an option:\n" + "1-Addition\n" + "2-Subtraction\n" + "3-Exit");
            try {
                option = Integer.parseInt(input2.nextLine());
                if (option < 1 || option > 3) {
                    throw new IllegalArgumentException();
                }
                // ...Place here the rest of code (which is based on the value of option)
            } catch (IllegalArgumentException e) {
                System.out.println("This is an invalid entry. Please try again.");
                valid = false;
            }
        } while (!valid);
    }
}

A sample run:

Choose an option:
1-Addition
2-Subtraction
3-Exit
x
This is an invalid entry. Please try again.
Choose an option:
1-Addition
2-Subtraction
3-Exit
10.5
This is an invalid entry. Please try again.
Choose an option:
1-Addition
2-Subtraction
3-Exit
1
Arvind Kumar Avinash
  • 50,121
  • 5
  • 26
  • 72
  • I think OP's issue is the af.close() call in the calculator method. Refer here https://stackoverflow.com/a/13042296/13163131 – humble_barnacle Apr 15 '21 at 18:13
  • @humble_barnacle - Thanks for the comment. It is something that I mention in almost all of my answers related to `Scanner` but somehow, I missed to mention it in this answer. I've added this point as well. – Arvind Kumar Avinash Apr 15 '21 at 18:25
  • Also to note that in case Scanner is needed by a function called by a particular function which already invoked Scanner, then the Scanner object may be passed as argument or Singleton pattern maybe used. I feel this is important to mention as OP is new – humble_barnacle Apr 15 '21 at 21:16
-1

Did you remember to import java.util.Scanner? Or how do you compile your source file? I had that same error message when compiled with gradle and i was missing one tiny line in gradle build file.

  • hi, i imported-import java.util.Scanner; can it cause a problem with my file?;how can i fix it? – Infinite Apr 02 '20 at 13:58
  • I did try your code and i think your problem is multiple scanner objects. I whould use only one scanner object, make it static and place it right before main function. And you can close your scanner class normally at end of the main function. – Raine M. Apr 03 '20 at 02:27