Что не так с этим циклом while?

boolean r = false ; int s = 0 ;
while (r == false) ; 
{
    s = getInt() ; 
    if (!(s>=0 && s<=2)) System.out.println ("try again not a valid response") ; 
    else r = true ; 
}

Текст никогда не отображается, даже если введено число 3 или 123, и цикл никогда не завершается. Что здесь не так?


person David    schedule 09.04.2010    source источник
comment
Кроме того, это не бесконечный цикл, поэтому тег infinite-loop не имеет смысла.   -  person Daniel DiPaolo    schedule 10.04.2010
comment
На самом деле это бесконечный цикл. while (r == false) ; — это бесконечный цикл, ничего не делающий, так как r инициализируется значением false.   -  person Dave Costa    schedule 10.04.2010
comment
Перестаньте пытаться поставить несколько вещей в одну линию. Во всяком случае, это то, что вызвало вашу проблему. Как только вы привыкнете писать четко, вы обнаружите, что такого рода вещи случаются гораздо реже. Также установите свои предупреждения в eclipse выше - он должен был указать вам пустой оператор. Не просто решайте эту проблему, а устраняйте первопричины.   -  person Bill K    schedule 10.04.2010
comment
О! Насколько грустно, что я публикую принятый ответ, а затем продолжаю неправильно читать код во второй раз и засовываю ногу в рот, думая, что он сказал while (false)?   -  person Daniel DiPaolo    schedule 10.04.2010
comment
ГААААААААА! МОИ ГЛАЗА!!! Пожалуйста, подумайте о том, чтобы сделать отступ в этом операторе if. Даже самые простые операторы управления можно сделать нечитаемыми, загромождая все одной строкой, без отступов и без открывающих/закрывающих фигурных скобок. Кроме того, переработайте выражение в этом операторе if, чтобы оно не использовало отрицание (!) Очень редко вы хотите использовать отрицание составного логического выражения.   -  person luis.espinal    schedule 10.04.2010
comment
Не проще ли было пройтись по этому коду в отладчике, чтобы найти проблему?   -  person Kevin    schedule 10.04.2010


Ответы (7)


У вас есть точка с запятой после условия. Когда вы используете фигурные скобки, чтобы указать блок для вашего while, вы не используете точку с запятой.

person Daniel DiPaolo    schedule 09.04.2010
comment
Хе-хе... while (r==false) /*DO NOTHING*/ ; - person Armstrongest; 10.04.2010

Удалить ';' через некоторое время.

person Alex    schedule 09.04.2010

Другие указали на ошибку, но ваш код пугает другими способами, которые в конечном итоге сбивают вас с толку:

if (!(s>=0 && s<=2)) System.out.println ("try again not a valid response") ; 
else r = true ; 

Это плохо, потому что вы можете легко запланировать выполнение более чем одного оператора в случае предложения if или else. Используйте фигурные скобки и избегайте размещения условных операторов в одной строке:

if (!(s>=0 && s<=2))
{
    System.out.println ("try again not a valid response");
}
else
{
    r = true;
}

Его легче читать, и гораздо меньше шансов ввести трудно заметные ошибки.

person Jonathon Faust    schedule 09.04.2010
comment
Я не согласен с использованием фигурных скобок. Если это один оператор, то это один оператор. Из соображений стиля я буду делать отступы, но не буду использовать завитки для отдельных утверждений... однако это религиозная битва. - person Armstrongest; 10.04.2010
comment
@Atomiton абсолютно точно, я предпочитаю использовать их все время, потому что я, вероятно, вернусь и изменю их в какой-то момент, и тогда я облажаюсь, если не поставлю их туда изначально. По крайней мере, поместите их в другую строку - я надеюсь, что мы сможем договориться об этом :) - person Jonathon Faust; 10.04.2010
comment
Я никогда не использую фигурные скобки для одного оператора, и я часто возвращаюсь и добавляю к нему что-то еще, и я никогда случайно не забывал добавить фигурные скобки и не испортил свой поток управления... Если только я некоторое время не писал на python, а затем пришел вернуться к C, т.е. - person Carson Myers; 10.04.2010
comment
Я никогда не вернусь и не совершу эту ошибку. - person David; 10.04.2010
comment
Хотя я часто опускаю фигурные скобки в одной строке, я не могу защитить эту практику. Дело в том, что наличие брекетов там практически ничего не стоит, даже если они как-то немного сбивают вас с толку, то на то, чтобы еще раз взглянуть на них, уйдет меньше секунды. С другой стороны, оставляя их выключенными, скажем, даже один раз из тысячи операторов if (скажем, когда вы какое-то время писали на python, а затем возвращаетесь к C), если вы случайно облажались, это может занять минуты или часы. исправить - это неоправданно и довольно явно неправильно. Тем не менее, я чаще всего их оставляю... - person Bill K; 10.04.2010
comment
Мне нравится, когда люди говорят что-то вроде «Я никогда не вернусь и не совершу эту ошибку». Потому что к коду можете вернуться не вы, и в любом случае код, написанный более пары месяцев назад, вполне может быть написан кем-то другим. - person Paul McKenzie; 10.04.2010
comment
отдельные операторы на отдельной строке. это очевидно. - person Paul McKenzie; 10.04.2010

в то время как (г == ложь)

должно быть

пока(!р)

Несмотря на то, что все остальные говорили о точке с запятой, я думаю, что это неправильно :)

person John Vint    schedule 09.04.2010
comment
while(r == false) более явный и читабельный. Я полагаю, люди могли бы также утверждать, что это должно быть while(false == r), но я ненавижу это. В любом случае, дело не в том, что он «должен» изменить его на !r, потому что r — это логическое значение, поэтому в любом случае это не имеет значения, а это означает, что это просто вопрос стиля. - person Carson Myers; 10.04.2010
comment
Последовательное соблюдение соглашения r и !r вместо r == false и r == true позволяет избежать ошибок r = false и r = true (которые НЕ вызовут ошибки компиляции в java). Если вы хотите сделать его более понятным и читабельным, переименуйте r во что-то вроде continue или found. - person ILMTitan; 10.04.2010
comment
continue — это ключевое слово, поэтому имя переменной будет ужасным. Однако вы правы, такие имена переменных, как r и s, ужасны. Используйте современную IDE с автодополнением и назовите ее как-нибудь осмысленно, например, сделано или найдено. - person ajs410; 10.04.2010
comment
@ Майерс, я не согласен. Я думаю, что r == false - это вонючий код, и я бы никогда не хотел, чтобы кто-то использовал его в коде, с которым я работаю. - person John Vint; 10.04.2010

+1 Даниэлю ДиПаоло. Я решил опубликовать отдельный ответ, чтобы объяснить, почему это так.

В то время как циклы в Java могут быть записаны одним из двух способов. Если в теле цикла есть только одна строка, вы можете записать их в сокращенной форме:

while (true)
    System.out.println("While loop");

Это будет печатать «While loop» на консоли, пока программа не завершится. Другой вариант — указать тело цикла между фигурными скобками, как вы сделали выше:

int i = 0;
while (i < 10) {
    System.out.println("i = " + i);
    i++;
}

Это напечатает «i = 0», «i = 1», ..., «i = 9» каждое в отдельной строке.

Код, который вы разместили, путает их. В сокращенном цикле while синтаксический анализатор Java ожидает найти оператор между условием цикла while и точкой с запятой. Поскольку он не находит здесь оператора, цикл while выполняется, но ничего не делает; у него нет тела. Кроме того, поскольку у цикла нет тела, у вашей переменной r нет возможности принять новое значение; условие всегда оценивается как истинное, и цикл никогда не завершается.

Если бы вы отрицали условие в цикле while в вашем примере, т.е.

boolean r = false ; int s = 0 ;
while (r != false) ; 
{
    s = getInt() ; 
    if (!(s>=0 && s<=2)) System.out.println ("try again not a valid response") ; 
    else r = true ; 
}

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

person alastairs    schedule 09.04.2010

В дополнение к другим комментариям вы также должны изменить if на

if (s < 0 || s > 2)

Так гораздо понятнее.

person fish    schedule 10.04.2010
comment
+1 Безусловно, из-за отрицания читать то, что должно быть простым, утомительно. - person Jonathon Faust; 10.04.2010

Несвязанный ответ, я действительно рекомендую вам следовать рекомендациям по стилю Sun.

boolean r = false ; 
int s = 0 ;
while (r == false) {
    s = getInt() ; 
    if (!(s>=0 && s<=2)) {
        System.out.println ("try again not a valid response") ; 
    } else {
      r = true ;
    } 
}

Вы можете избавиться от переменной r и условия if/else, если вы сами оцениваете результат в цикле.

int s = 0;

while( ( s = getInt() ) < 0 || s > 2 ) {
    System.out.println( "Try again, not a valid response");
}
person Community    schedule 10.04.2010