Получение пользовательского ввода с помощью сканера

Я пытаюсь заставить сканер вводить данные в цикле. Как только пользователь хочет закончить, он может выйти из этого цикла. Я пробовал много разных способов сделать это, но всегда есть какая-то проблема. Это код:

private void inputEntries() {
    Scanner sc = new Scanner(System.in);
    System.out.println("Continue?[Y/N]");
    while (sc.hasNext() && (sc.nextLine().equalsIgnoreCase("y"))) {//change here
        System.out.println("Enter first name");
        String name = sc.nextLine();
        System.out.println("Enter surname");
        String surname = sc.nextLine();
        System.out.println("Enter number");
        int number = sc.nextInt();
        Student student = new Student(name, surname, number);
        students.add(student);
        try {
            addToFile(student);
        } catch (Exception ex) {
            Logger.getLogger(TextReader.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("Continue?[Y/N]");
    }
}

Проблема с приведенным выше кодом, которая также возникает при использовании разных методов, которые я пробовал, заключается в том, что когда пользователь вводит Y, Scanner пропустит первый ввод имени и перейдет к фамилии. Если пользователь вводит N, цикл останавливается корректно. Кто-то может объяснить, почему это происходит, и как это преодолеть с помощью класса Scanner?

p.s: выполнение чего-то вроде while(sc.nextLine().equals("Y")) приведет к завершению цикла до получения ввода от пользователя после первого запуска цикла.


person Giannis    schedule 21.10.2012    source источник


Ответы (4)


Это связано с тем, что вы используете Scanner#next метод. И если вы посмотрите на документацию этого метода, он возвращает следующий прочитанный токен.

Итак, когда вы читаете пользовательский ввод с помощью метода next, он не читает newline в конце. Который затем читается nextLine() внутри цикла while. Таким образом, ваш firstName содержит newline без вашего ведома.

Таким образом, вы должны использовать nextLine() в своем while, а не next().

Аналогично в случае с nextInt< /а> метод. Он также не читает новую строку. Итак, вы можете read использовать readLine и преобразовать его в int с помощью Integer.parseInt. Он может выдать NumberFormatException, если входное значение не может быть преобразовано в int. Таким образом, вы должны обращаться с этим соответствующим образом.

Вы можете попробовать следующий код: -

Scanner sc = new Scanner(System.in);
System.out.println("Continue?[Y/N]");
while (sc.hasNext() && (sc.nextLine().equalsIgnoreCase("y"))) {//change here
    System.out.println("Enter first name");
    String name = sc.nextLine();
    System.out.println("Enter surname");
    String surname = sc.nextLine();
    System.out.println("Enter number");
    int number = 0;
    try {
        number = Integer.parseInt(sc.nextLine());
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    }
    System.out.println("Continue?[Y/N]");
}

Но обратите внимание: если вы введете значение, которое не может быть передано в Integer.parseInt, вы получите исключение, и этот ввод будет пропущен. В этом случае вам нужно обработать это, используя цикл while.

Или, если вы не хотите выполнять эту обработку исключений: -

Вы можете добавить empty sc.nextLine() после sc.nextInt(), чтобы использовать оставшиеся newline, например:

    // Left over part of your while loop

    String surname = sc.nextLine();
    System.out.println("Enter number");
    int number = sc.nextInt();
    sc.nextLine(); // To consume the left over newline;
    System.out.println("Continue?[Y/N]");
person Rohit Jain    schedule 21.10.2012
comment
Действительно работает. Хотя я не совсем уверен, почему nextInt не работал. Я набрал число и нажал Enter.. - person Giannis; 21.10.2012
comment
@ Яннис. Если вы видите документацию nextInt, он говорит, что считывает целочисленный токен next, таким образом, оставляет новую строку, которая также будет частью ввода. - person Rohit Jain; 21.10.2012
comment
@ Яннис. Итак, этот newline будет прочитан в следующий раз, когда вы вызовете nextLine, и, следовательно, эта часть чтения будет пропущена. - person Rohit Jain; 21.10.2012
comment
@DavidKroukamp. Спасибо. :) эта часть всегда является проблемой для новичков, когда они получают пользовательский ввод со сканером. - person Rohit Jain; 21.10.2012
comment
@RohitJain, даже я скучал по нему, пока не использовал nextLine() и не прочитал твой пост: P - person David Kroukamp; 21.10.2012
comment
Правильно понял, теперь должен был проверить доктора. Я собираюсь спрятаться в пещере и сжечь свою степень для тепла ... :P - person Giannis; 21.10.2012
comment
@ Яннис. Здорово. Помните, каждый раз, когда вы видите странное поведение с каким-то предопределенным методом, у вас всегда есть documentation на что нужно обратить внимание. Они говорят, что на самом деле будет делать этот метод. - person Rohit Jain; 21.10.2012
comment
sc.next() не устранил проблему (после nextInt). Используемый сч. пропустить(\n) вместо этого. - person Giannis; 21.10.2012
comment
@ Яннис. Ой! Извиняюсь. sc.next() не будет читать newline. Он просто читает следующий токен. Вместо этого вы можете использовать sc.nextLine. Я улучшу свой пост. - person Rohit Jain; 21.10.2012

  • Используйте equalsIgnoreCase(..), чтобы Y или N не были строчными, и наоборот.
  • Не используйте sc.next(), а sc.nextLine() для достижения желаемого, потому что next() читается только до следующего пробела, а nextLine() читается до следующего \n разрыва.
  • Не используйте nextInt() для чтения всех данных как String с последующим преобразованием, потому что nextInt() похоже на next() и не считывается до следующего \n.

Попробуйте это так:

Scanner sc = new Scanner(System.in);
System.out.println("Continue?[Y/N]");

while (sc.hasNext() && (sc.nextLine().equalsIgnoreCase("y"))) {//change here

    System.out.println("Enter first name");
    String name = sc.nextLine();

    System.out.println("Enter surname");
    String surname = sc.nextLine();

    System.out.println("Enter number");

    int number=0;

    try {
    number = Integer.parseInt(sc.nextLine());//read int as string using nextLine() and parse
    }catch(NumberFormatException nfe) {
        nfe.printStackTrace();
    }

    System.out.println("Continue?[Y/N]");
}
person David Kroukamp    schedule 21.10.2012
comment
Продолжить?[Д/Н] Д Введите имя dsa Введите фамилию asd Введите число 21 Продолжить?[Д/Н] Д ПОСТРОИТЬ УСПЕШНО (общее время: 15 секунд) Вот что происходит. - person Giannis; 21.10.2012
comment
Я копирую и вставляю строку while, и происходит то, что показано в комментарии. У вас работает?? - person Giannis; 21.10.2012
comment
@ Яннис, у вас есть Enter number 21 Continue?, вы не включили этот фрагмент во фрагмент ваших вопросов, включая весь код, что-то еще может быть виновато - person David Kroukamp; 21.10.2012
comment
@Rohit Jain решил, что я должен использовать nextLine и parseInt .. Все еще странно, что nextInt вызывает проблемы, хотя .. - person Giannis; 21.10.2012
comment
@Giannis, как сказал, потому что nextInt читает следующий токен, а не до следующей новой строки - person David Kroukamp; 21.10.2012
comment
@ Яннис. В своем посте я дал обходной путь, чтобы не использовать обработку исключений. Вы можете посмотреть на это. - person Rohit Jain; 21.10.2012

Вы могли бы использовать

String abc = "abc";
String answer = "null";
while (abc.equals("abc")
{
if (answer.equals("n")
{
break;
}
while (answer.equals("y"))
{
//Put your other code here
System.out.print("Continue? [y/n]")
answer = input.nextLine();
if (answer.equals("n")
{
break;
}
}
}

Это должно остановить программу, когда ввод

"n"

Вам также нужно будет импортировать и создать сканер следующим образом:

//This is how you import the Scanner
import java.util.Scanner;
//This is how you create the Scanner
Scanner input = new Scanner(System.in);
/**
*The name
*/
"input"
/**
*is used because of
*/
input.nextLine
person spacegeek224    schedule 24.10.2013

person    schedule
comment
1 1 000 123 11111 12345 0000000 1234567 111111111123456789 1234321 1234567 12321 12345 121 123 1 1 выход - person suvradeep chakraborty; 27.09.2015
comment
Я отформатировал ваш код, если вы добавите вывод к ответу и добавите какое-то объяснение, это действительно может быть полезно. Вы всегда можете отредактировать свой собственный ответ. - person Stefan Dollase; 27.09.2015