{
static Scanner reader = new Scanner(System.in);
public static void main(String[] args)
{
int x=0, count=0, sum=0;
while (sum<=100)
{
x=(int)(10*Math.random());
count++;
sum+=x;
}
sum-=x;
count--;
System.out.println("Сумма="+sum+" количество значений="+count);
}
}
В решении есть несколько особенностей, на которые очень важно обратить внимание:
1. В заголовке while (sum<=100) использовано условие, связанное с ограничением, налагаемым, в соответствии с условием задания, на сумму серии; и сумма эта, разумеется, должна быть в начале класса обнулена.
2. После окончания цикла, то есть после перехода исполнения к команде, которая расположена в классе после цикла, сумма уменьшается на значение последнего значения в серии, а переменная-счетчик уменьшается на 1. Это делается потому, что цикл прерывается после того, как сумма превысит ограничение, то есть значение 100.
3. Обратите значение на то, что переменная х инициализирована значением 0. Это делается из-за того, что значения переменой х создаются внутри цикла, а после выхода из цикла переменную-сумму надо уменьшить на последнее значение переменной х. однако, без инициализации этой переменной до начала цикла, еще на этапе компиляции класса возникает ошибка, смысл которой – "переменная х может не получить значения". Эта ошибка связана с тем, что язык Java очень придирчиво и требовательно относится к вероятности того, что переменная может остаться неинициализированной. А поскольку свои значения переменная х получает в теле цикла, которые, как может случиться, ни разу не будет исполняться, то язык Java, уже на этапе компиляции, требует не допустить даже вероятности такой ситуации. Вот и приходится инициализировать переменную хотя бы значением 0 еще до цикла; разумеется, что с таким же успехом ее можно было бы инициализировать любым другим значением.
|
|
Раздел №19 (часть 2).
Структура и использование цикла do…while
В языке Java существует вариант цикла while, который выглядит следующим образом:
· В заголовке используется служебное слово do
· Тело цикла заключено в фигурные скобки
· После фигурной скобки, закрывающей тело цикла, записывается служебное слово while() с условием в круглых скобках – совершенного аналогично тому, как это делается в "обычном" цикле while
Разница между "обычным" циклом while и циклом do…while – в том, что "обычный" цикл while может не выполняться ни разу, а цикл do…while обязательно выполняется как минимум в первый раз. И только после выполнения прохода проверяется условие – повторить исполнение цикла еще раз или нет.
Раздел №20.
Вложенные циклы
Существуют ситуации, которые можно описать выражением "цикл в цикле" – то есть когда один повторяющийся процесс выполняется внутри другого повторяющегося процесса.
|
|
Например, дни недели повторяются снова и снова внутри годового цикла, который состоит из повторяющихся месяцев.
Еще один пример из "истории времен": секунды повторяются снова и снова в часовом цикле, где минуты повторяются друг за другом.
Если мы выпишем числа от 100 до 999, то легко увидим, что цифры в позиции "число единиц" повторяются снова и снова в каждом десятке, да и цифры в позиции "число десятков" повторяются снова и снова в каждой сотне.
Думаю, что каждый может привести дополнительные примеры ситуаций, когда одно повторяющееся действие выполняется внутри другого повторяющегося действия: это называется "цикл в цикле" или "вложенные циклы". Вложенные друг в друга, то есть когда один цикл (или даже несколько циклов, идущих один за другим, по отдельности) вложен в другой цикл, внутрь другого цикла.
Вот, например, блок (группа команд, часть программного кода), который проверяет, является ли переменная num простым числом. Делается это с помощью подсчета количества делителей этой переменной – начиная с 2 и до "середины" num (нет смысла искать делители, которые больше половины проверяемого числа, потому что таких делителей в принципе быть не может).
int count=0, num=reader.nextInt();
for (int i=2; i<=(num/2); i++)
if (num%i==0) count++;
В случае, если переменная num действительно является простым числом, значение переменной count после исполнения этого блока останется равным 0, потому что ни одного делителя у простого числа нет.
Разумеется, у каждого числа вообще, и, в том числе, у простого числа, есть два делителя: это единица и само число. При желании только что приведенный блок можно было бы записать, с учетом только что сказанного, несколько иначе:
int count=0, num=reader.nextInt();
for (int i=1; i<=num; i++)
if (num%i==2) count++;
понятно, что в этом случае значение переменной count после окончания проверки должно быть равно не 0, а 2 9единица и само числа – два делителя любого числа).
А теперь усложним задачу: надо найти и вывести на экран все простые двузначные числа. Для этого мы организуем цикл по всем двузначным числам (можно начать с 13, но "для порядка" мы все же начнем с 10), а внутри этого цикла, то есть на каждое двузначное число, задействуем приведенный выше блок, в котором тоже есть цикл! Вот так и получится у нас "конструкция", в которой один цикл будет вложен в другой: внешний цикл будет перебирать одно за другим двузначные числа, а внутренний цикл будет перебирать для каждого такого числа все его возможные делители. Как вы понимаете, реализацией слова "перебирать" является ни что иное, как использование цикла.
int count=0;
for (num=10; num<=99; num++)
{
for (int i=2; i<=(num/2); i++)
if (num%i==0) count++;
if (count==0)
System.out.println(num);
count=0;
}
Работать эта конструкция будет так:
· Сначала переменная num во внешнем цикле принимает очередное значение (первым будет значение 10, потом значение 11, далее – значение 12… и так до значения 99).
· Затем полностью выполняются все проходы (повторы) во внутреннем цикле, во время которых числа проверяются на то, являются ли они делителем значения переменной num.
· В случае, если в переменной-счетчике осталось начальное значение 0, на экран выводится значение переменной num, потому что оно, это значение, действительно является простым числом.
· Очень важный момент, который (особенно на первых порах), ускользает от внимания: перед повтором внешнего цикла снова обнуляется переменная-счетчик. Делается это потому, что для каждого нового числа все проверки на "делитель-не делитель" надо будет выполнять заново.
Обратите внимание: во внешнем и внутреннем циклах мы использовали разные переменные-счетчики; делается это для того, чтобы не происходила путаница при счете повтором каждого из циклов.
|
|
Кстати, использование и для внешнего, и для внутреннего цикла одной и той же переменной-счетчика повторов, является чрезвычайно распространенной ошибкой.
Разберем еще один пример: " Напишите класс, который выводит на экран прямоугольник из символов #. При этом размеры прямоугольника, то есть количество строк, и количество знаков в каждой строке указывается введением с клавиатуры двух чисел: первое – количество строк, второе – количество знаков в каждой строке ".
Это значит, что, при введении с клавиатуры значений 4 и 7, на экран должен выводиться вот такой прямоугольник (4 строки по 7 знаков в каждой строке):
#######
#######
#######
#######
Для того чтобы "организовать" нужное количество строк, мы используем внешний цикл, а для того, чтобы гарантировать вывод нужного количества знаков в каждой строке, мы используем внутренний цикл. Кроме того, для того, чтобы после окончания очередной строки из символов # осуществлялся переход к новой строке, после окончания внутреннего цикла мы используем команду "пустого" вывода на экран.
Мы приводим фрагмент такого класса:
int strok, znakov;
strok=reader.nextInt();
znakov==reader.nextInt();
for (j=1; j<=strok; j++)
{
for (i=1; i<=znakov; i++)
System.out.print("#");
System.out.println();
}
Раздел №21.
Методы
На определенном этапе классы становятся все более и более сложными и, одновременно с увеличением сложности, разрастаются с точки зрения количества строк кода. Кроме того, в них начинают появляться части (блоки), которые повторяют друг друга, что просто нелогично и непродуктивно.
На этом этапе стоит начать использовать в классе новый инструмент, который называется "методы"; вот им и будет посвящен этот раздел.