2015-11-12 3 views
1
public static void main(String[] args) 
    { 
     Scanner in = new Scanner(System.in); 

     System.out.print("Please enter a digit: "); 
     int digit = in.nextInt(); 

     boolean isAnInteger = false; 
     while (isAnInteger) 
     { 
      if (digit >= 10) 
      { 
       System.out.println("Please enter an integer: "); 
      } 
      else 
      { 
       System.out.println("Correct! " + digit + " is an integer!"); 
      } 
     } 
    } 

В настоящее время я занимаюсь AP Computer Science, и мне любопытно, как решить эту (хотя и основную) проблему. Я знаю, что «while» петли продолжают все, что находится в их соответствующих фигурных скобках, когда условие в их скобках продолжает встречаться.Как исправить этот бесконечный цикл? (AP Computer Science)

Когда я попытался установить условие while к while (digit >= 10), это привело к бесконечному циклу (поправьте меня, но это связано с тем, что если пользователь вводит цифру 10 или больше, то условие будет СОХРАНИТЬ неудовлетворенными и продолжайте бесконечно). Итак, я попытался установить условие while для некоторого логического значения, а if вложен внутри с прежним условием. Теперь, когда пользователь вводит 10, после этого ничего не происходит, и программа заканчивается.

Как написать вышеприведенный код, чтобы система продолжала печатать «Пожалуйста, введите целое число:», если условие (ввода 10 или больше и наоборот) продолжает выполняться?

+2

Почему бы вам не обновить 'isAnInteger' нигде в вашем цикле? – Makoto

+1

@ Макото это правильно. Как и сейчас, ваша петля никогда не должна выполняться вообще (не говоря уже о бесконечности), так как 'isAnInteger' установлен на' false'. – Windle

+0

следует «целое число» быть «цифрой» в этом утверждении ?: 'System.out.println (« Пожалуйста, введите целое число: »);' и такое же в другом System.println (...)? –

ответ

1

Eсть основная проблема «плохого дизайна» в том, что переменная isAnInteger имеет более широкую область видимости (она живет за последней строкой, которая ей нужна).

«Правильный» подход - это цикл, который содержит логику, которая определяет «целостность» ввода и не оставляет переменные в области, когда контур заканчивается, кроме захваченного ввода, конечно, digit.

Далее, вы хотите, чтобы отделить проблемы захвата входа с проверкой, поэтому сначала необходимо создать метод, который получает цифру:

private static int readNumber(Scanner in) { 
    System.out.print("Please enter a digit: "); 
    int digit = in.nextInt(); 
    in.nextLine(); // you must clear the newline char from the buffer 
    return digit; 
} 

Далее, написать простой while() цикл, который продолжает чтение до тех пор, пока он получает хорошее вход:

int digit = 10; // bad input 
while (digit > 9) { 
    digit = readNumber(in); 
} 

Собираем все вместе с окончательным сообщением:

public static void main(String[] args) { 
    Scanner in = new Scanner(System.in); 
    int digit = 10; // initialize with "bad" input 
    while (digit > 9) { 
     digit = readNumber(in); 
    } 
    System.out.println("Correct! " + digit + " is an integer!"); 
} 

private static int readNumber(Scanner in) { 
    System.out.print("Please enter a digit: "); 
    int digit = in.nextInt(); 
    in.nextLine(); // you must clear the newline char from the buffer 
    return digit; 
} 

Этот подход делает код намного легче читать и понимать.
Также обратите внимание на то, что не существует повторяющегося кода (например, строка, запрашивающая цифру или ввод для чтения).

+0

'in.next(); // вы должны очистить символ новой строки из буфера '...' next' не будет этого делать. – Tom

+0

Это поведение не связано с используемым разделителем. Оба, [JavaDoc] (http://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#next--) и [простой тест] (http: // pastebin. com/pKbgJ9hD) (#) показывают, что 'next' не будет использовать разделитель, если это единственное, что нужно прочитать из источника. (#) Вы можете вставить весь ввод сразу, затем вы получите пустую строку из 'nextLine', или вы можете записать ее вручную, после чего вы увидите, что' next' блокирует поток, пока не получит токен. – Tom

+0

@Tom Вы совершенно верны. Теперь я знаю разницу при использовании разделителя по умолчанию (извините: я редко использую сканер) – Bohemian

0

Основная концептуальная часть здесь заключается в том, что вы не обновляете свое значение нигде внутри вашего цикла. Поскольку он не обновляется, он всегда будет оставаться значением, когда он вступил в цикл (то есть digit >= 10 останется истинным до тех пор, пока программа не перестанет работать).

Вы должны обновить свои значения внутри своего цикла.

Однако есть еще одна концепция, которую вам не хватает: вам гарантированно будет работать цикл хотя бы один раз, поэтому вместо этого вы должны использовать цикл do...while.

Обратите внимание, что я использую nextLine(), чтобы избежать каких-либо проблемных вопросов nextInt().

(О, кстати: любое число, которое вы ищете это целое Вы должны сообщить, что вы ищете целое число меньше 10, а..)

System.out.print("Please enter a digit: "); 
int digit = Integer.parseInt(in.nextLine()); 

boolean isAnInteger; 

do { 
    if (digit >= 10) { 
     System.out.println("Please enter an integer: "); 
     digit = Integer.parseInt(in.nextLine()); 
     isAnInteger = false; 
    } else { 
     System.out.println("Correct! " + digit + " is an integer!"); 
     isAnInteger = true; 
    } 
} while (isAnInteger); 
0

Да, у Макото это право.

Вы никогда не обновляете свои значения внутри цикла while. В вашем оригинальном случае, когда вы просто хотели распечатать Please enter an integer:, вы никогда не запрашиваете ввод сразу после этой строки. Ваше исходное значение digit будет по-прежнему больше или равно 10 и будет продолжать цикл.

Даже с текущим кодом, вы все равно будете работать в бесконечный цикл, если ваше значение digit меньше 10. Обратите внимание, как логическое isAnInteger не зависит от того, вашего digit меньше 10.

Лучшим способ чтобы исправить это, используя что-то вроде этого:


    in = new Scanner(System.in); 

    System.out.print("Please enter a digit: "); 
    int digit = in.nextInt(); 

    while (digit >= 10) 
    { 
     System.out.println("Please enter an integer: "); 
     digit = in.nextInt(); 
    } 
    System.out.println("Correct! " + digit + " is an integer!"); 

Что это делает он продолжает проверять, если цифра больше или равна 10. Если да, то он будет продолжать запрашивать у пользователя для входа. Если в любое время во время итерации цикла пользователь вводит значение меньше 10, он не будет выполнять следующую итерацию и покидает цикл. Затем он будет выполнять последние println.

Однако, если первый вход меньше 10, он пропустит цикл while и выполнит println внизу.

Если вы хотите использовать логическое значение, как вы сделали, вы можете сделать это таким образом:


    in = new Scanner(System.in); 

    System.out.print("Please enter a digit: "); 
    int digit = in.nextInt(); 

    bool isAnInteger = true; 
    if (digit >= 10) 
     isAnInteger = false; 

    while (!isAnInteger) // checks if digit is not an integer 
    { 
     System.out.println("Please enter an integer: "); 
     digit = in.nextInt(); 

     if !(digit >= 10) 
      isAnInteger = true; 
    } 
    System.out.println("Correct! " + digit + " is an integer!"); 

способ Макото использования do while цикла, вероятно, лучше, хотя это может быть лучшим способом визуализируя его (поскольку вы использовали цикл while).