2014-09-24 4 views
-3

Я хочу спросить пользователя, хочет ли он создать файл с именем file.elt или нет. Я пытаюсь сделать это с помощью оператора switch, используя класс Scanner.Бесконечный цикл при использовании сканера - java

Вот мой код:

System.out.println("Do you want to create the file.elt? (Y/N)"); 
      strOption=sc.nextLine(); 

     OUTER: 
     while (sc.hasNext()) { 
      switch (strOption) { 
       case "Y": 
       case "y": 
        elements.createElements(file); 
        break OUTER; 
       case "N": 
       case "n": 
        System.out.println("There will be no file.elt created! ."); 
        break OUTER; 
       default: 
        System.out.println("Please, type Y or N."); 
        strOption=sc.nextLine(); 
        break; 
      }     
     } 
     sc.close(); 

Объект sc объявлен в начале программы, где я попросить имя файла.

sc декларация:

String file; 

    Scanner sc = new Scanner(System.in); 

    System.out.println("Type the name of the file .dat ."); 

    file=sc.nextLine(); 

Проблема заключается в том, что цикл в то время бесконечно, и я не знаю, почему.

ответ

5

Вы не обновляете strOption. Вы должны переместить strOption=sc.nextLine(); внутри петли while Кроме того, как указал TheLostMind, замените hasNext на hasNextLine.


Редактировать

Вы могли бы рассмотреть, чтобы переключиться на Console. Кроме того, вы можете создать confirm метод полезности, так как это довольно распространенная задача:

private Console console; 

... 
console = System.console(); 
... 
if (confirm("Do you want to create the file.elt? (Y/N)")) { 
    elements.createElements(file); 
} else { 
    System.out.println("There will be no file.elt created! ."); 
} 
... 

private boolean confirm(String message) { 
    String answer = console.readLine(message); 
    while (!answer.matches("[YyNn]")) { 
     answer = console.readLine("Please, type Y or N."); 
    } 
    return "Y".equalsIgnoreCase(answer); 
} 

Примечание: doesn't work in eclipse.

+1

изменить также 'sc.hasNext()' в 'sc.hasNextLine()' – TheLostMind

+0

Great! Спасибо! – daro

1

Сканер основан на состоянии, и немного сложно. Я бы не использовал его для не-токенов.

//strOption=sc.nextLine(); 
OUTER: 
while (sc.hasNextLine()) { 
    strOption=sc.nextLine(); 
... 
     default: 
      System.out.println("Please, type Y or N."); 
      //strOption=sc.nextLine(); 
1

2 варианта:

  1. Поскольку sc.hasNext() всегда верно. вам нужно вызвать sc.nextLine авансам этот сканер мимо текущей строки

  2. sc.hasNext() блокирует (как описано в documents)

, если сп сказать, если это действительно бесконечный цикл или блокирующий вызов - вы будет знать, как его решить (просто добавьте трассировку в начале цикла, запустите программу и проверьте выходную консоль)

1

Во-первых, не используйте такие метки, как OUTER, если вы не знаете, что делаете. В этом случае он не нужен.

sc.hasNext() возвращает true (иначе вы бы даже не вошли в цикл), и в цикле вы ничего не сделаете, чтобы изменить это состояние (вы не «потребляете» входной поток).

Прежде чем вы войдете в цикл, вы прочтете первую строку, после чего, по-видимому, будет прочитано больше ввода, но вы никогда не читаете этот ввод, поэтому sc.hasNext() продолжает возвращать true, а цикл while никогда не заканчивается.

Ваш break OUTER; перерывается в петлю, определенную в OUTER:, что означает, что она ломается до цикла while, не OUT из цикла while. Обычно люди используют эту конструкцию для выхода из внутреннего цикла во внешний цикл, но, как я уже говорил, вам лучше не использовать эту конструкцию.

EDIT: Я перепутал помеченные перерывы с надписью продолжается. В принципе, разрыв здесь работает по назначению, но ярлык лишний (и я по-прежнему не рекомендую использовать ярлыки).

Проблема в том, что первая строка ввода, которую вы прочитали, по какой-то причине, по-видимому, не равна «y», «Y», «n» или «N», и поскольку вы не потребляете вход, sc.hasNext() и strOption по-прежнему содержит ту же строку, которая не соответствует ни одному из утверждений вашего случая, то есть цикл будет продолжаться бесконечно.

Либо используйте обычный break;, либо исправьте свою петлю, чтобы она потребляла вход.

Например:

System.out.println("Do you want to create the file.elt? (Y/N)"); 

while (sc.hasNext()) 
{ 
    String inputString = strOption=sc.nextLine(); 
    // handle inputString   
} 
sc.close(); 
+1

Разрыв с меткой нарушает * * внешний контур, но поскольку внешний контур сразу заканчивается, он в большинстве случаев эквивалентен разрыву * out * внешнего цикла. (см. http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.15) –

+0

благодарит за отзыв! На самом деле, я никогда не использовал лейблы раньше ... спасибо u! Как вы можете видеть, я совершенно новый в программировании на Java. – daro

+0

@ThomasStets Вы правы. Я смутил помеченные перерывы с надписью продолжается. – Buurman

Смежные вопросы