Бесконечный цикл while в Java

Привет! Я пытаюсь сделать некоторую проверку ввода данных, но я не смог понять это. Я получаю бесконечный цикл while, когда пытаюсь проверить, является ли первый введенный символ буквой. . . .

Спасибо за вашу помощь!

public class methods
{
    public static void main(String args[]) throws IOException
    {
        String input ="";
        int qoh=0;
        boolean error=true;

        Scanner keyboard = new Scanner (System.in);

        //while (error)
        //{
            //error=true;

        while (error==true)
        {
           System.out.print("\nEnter Quantity on Hand: ");
           input = keyboard.nextLine();

           if (input.length() <1)
           {
               System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
               error=true;
               System.out.println(qoh);
               System.out.println(input);
            }
            else
            {
                error=false;
            }
        }

        error = true;

        while (error==true)
        {
            if (Character.isLetter(input.charAt(0)))
            {
                System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
                error=true;
                System.out.println(qoh);
                System.out.println(input);
             }
             else
             {
                 qoh = Integer.parseInt(input);
                 error=false;
              }
          }
      }
  }

person Andy    schedule 26.02.2010    source источник
comment
примечание: в то время как (ошибка == истина) может быть записано как пока (ошибка)   -  person basszero    schedule 26.02.2010


Ответы (4)


У вас нет input = keyboard.nextLine(); во втором цикле while.

Вы можете реорганизовать свой код, чтобы запрашивать новый ввод только при возникновении ошибки. Итак, сразу после sysout "ОШИБКА..."

Дополнительно: я бы сделал это по-другому. «Ошибка = истина» в начале немного сбивает с толку, потому что ошибки может и не быть.

Вы могли бы, например, написать метод с именем tryProcessLine, который считывает входные данные и возвращает true, если все в порядке, и false, если произошла ошибка, а затем просто выполните что-то вроде while(!tryProcessLine()){ }

Рабочий пример ниже:

import java.io.IOException;
import java.util.Scanner;

public class Methods {

  private static int qoh;

  public static void main(String args[]) throws IOException {

    while (!tryProcessLine()) {
        System.out.println("error... Trying again");
    }

    System.out.println("succeeded! Result: " + qoh);

  }

  public static boolean tryProcessLine() {

    String input = "";

    Scanner keyboard = new Scanner(System.in);

    System.out.print("\nEnter Quantity on Hand: ");

    input = keyboard.nextLine();

    try {
        qoh = Integer.valueOf(input);

        if (qoh < 0 || qoh > 500) {
          System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
          return false;
        } else {
          return true;
        }
    } catch (NumberFormatException e) {
        System.out.println("\n**ERROR06** - Quantity on hand must be numeric");
        return false;
    }
  }
}
person Fortega    schedule 26.02.2010
comment
-1: это не причина бесконечного цикла. Первый цикл предназначен для чтения первой непустой строки, тогда как я предполагаю, что второй цикл должен проверять, что эта строка содержит только числовые символы (а не читать другую строку ввода). - person Adamski; 26.02.2010
comment
Я предполагаю, что он хочет получить новый ввод, когда произойдет ошибка во втором цикле. В противном случае второй цикл не должен быть циклом. Потому что теперь, когда во втором цикле есть «ошибка», новый ввод не запрашивается, и «ошибка == истина» всегда будет истинным... - person Fortega; 26.02.2010
comment
Я предполагаю, что он хочет прочитать первую непустую строку ввода и попытаться преобразовать ее в целое число. Я не думаю, что ОП вообще требует двух циклов. - person Adamski; 26.02.2010

Проблема именно в этом разделе:

                        while (error==true)
                        {
                            if (Character.isLetter(input.charAt(0)))
                            {
                                System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
                                error=true;
                                System.out.println(qoh);
                                System.out.println(input);
                            }
                            else
                            {
                                qoh = Integer.parseInt(input);
                                error=false;
                            }
                        }

Как только у вас есть буква в первой позиции, этот цикл никогда не может завершиться. Он проверяет, стоит ли буква на первой позиции (есть), печатает ее и повторяет. Попробуйте изменить на:

                            while (error==true)
                            {
                                if (Character.isLetter(input.charAt(0)))
                                {
                                    System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
                                    error=false;

                                    ...

Кроме того, еще пара вещей:

while (error == true) можно сократить до while(error).

Кроме того, Integer.parseInt выдаст NumberFormatException, если ввод не является целым числом — вам нужно поймать и обработать это.

Кроме того, зачем вообще нужен второй цикл? Похоже, предполагается только проверка ввода - если это так, вы можете переместить эту логику в первый цикл и исключить второй. Используйте циклы только для вещей, которые должны повторяться (например, ввод пользователем входных данных). Нет необходимости многократно проверять один и тот же вход.

person danben    schedule 26.02.2010

Бесконечный цикл возникает из-за того, что второй цикл while неоднократно проверяет, является ли первый символ в строке (input.charAt(0)) буквой. Если предположить, что результат этой проверки верен, цикл никогда не завершится.

Ваш код можно упростить до чего-то вроде:

Integer qty = null;

while (scanner.hasNext() && qty == null) {
  String line = scanner.next();
  try {
    qty = Integer.parseInt(line);
  } catch(NumberFormatException ex) {
    System.err.println("Warning: Ignored non-integer value: " + line);
  }
}

if (qty == null) {
  System.err.println("Warning: No quantity specified.");
}
person Adamski    schedule 26.02.2010

Если это символ, вы допускаете, что ошибка все еще = true, что заставляет этот цикл продолжаться вечно, вы никогда не возвращаетесь к началу и не читаете другую строку.

Вот некоторый код, который делает то, что вы хотите, и структурирован немного лучше.

public class ScanInfo {

  Scanner keyboard = new Scanner(System.in);

  public ScanInfo(){
    String line = getLineFromConsole();
    while(null != line && !"quit".equals(line)){
      if(isValidInput(line)){
        int validNumber = Integer.parseInt(line);
        System.out.println("I recieved valid input: "+validNumber);
      }else{
        System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
      }
      line = getLineFromConsole();
    }

  }

  private boolean isValidInput(String line){
    //basic sanity
    if(null == line || line.length() < 1){
      return false;
    }


    try {
      int number = Integer.parseInt(line);

      return (number >= 0 && number <= 500);

    } catch (NumberFormatException e) {
      return false;
    }

  }


  public static void main(String[] args) {
    new ScanInfo();

  }

  public String getLineFromConsole(){
    System.out.print("\nEnter Quantity on Hand: ");
    return keyboard.nextLine();

  }

}
person Kylar    schedule 26.02.2010
comment
Почему вы дважды анализируете ввод в целое число? - person Adamski; 26.02.2010
comment
quit != строка должна быть !quit.equals(line) - person Fortega; 26.02.2010
comment
Я анализирую целое число дважды, потому что я ленив и неправильно его инкапсулировал. Fortega: внес изменения. - person Kylar; 03.03.2010