[Java] Циклы for/while и массивы
По прошлому ДЗ
Подумайте как можно проще решить задание про определение возраста? Некоторые использовали следующий трюк - вместо сравнения даты внутри года через много сравнений месяца и дня - достаточно ввести монотонную биекцию между датой и числом, и тогда достаточно сравнить просто числа:
int month1 = 6;
int day1 = 27;
int month2 = 3;
int day2 = 29;
int x = month1 * 32 + day1;
int y = month2 * 32 + day2;
if (x < y) {
System.out.println(day1 + "." + month1 + " is before " + day2 + "." + month2);
}
Почему в этом коде вместо 31 дня в месяце можно думать что в месяце 32 или вообще 100 дней? Влияет ли это на ответ?
А можно ли еще проще? Что если посмотреть на два таких числа:
int x = year1 * 12 * 32 + month1 * 32 + day1;
int y = year2 * 12 * 32 + month2 * 32 + day2;
Может быть мы можем из них рассчитать сколько полных лет прошло? Сколько полных лет между этими двумя переменными зажато? (воображаемых лет по 32 дня в каждом месяце)
Точно ли это всегда правильный ответ и от числа дней в месяце ничего не зависит?
Покрытые темы
int[] values; // объявленная переменная в которой может храниться массив (пока что его нет т.к. мы его не создали)
values = new int[10]; // а вот теперь мы создали новый массив размера 10 и положили его в эту переменную
int firstValue = values[0]; // индексация С НУЛЯ, поэтому первый элемент под индексом 0
int lastValue = values[9]; // а ПОСЛЕДНИЙ элемент (т.е. 10-ый) - под индексом 9
values[0] = 100; // положили в массив первым элементом сотню
// создавать массив можно и размера определяемого переменной:
int n = scanner.nextInt(); // спросили у пользователя сколько слов он планирует ввести
String[] words = new String[n];
for (int i = 0; i < n; i = i + 1) {
// этот код выполнится для всех i для которых выполняется условие (i < n) начиная с (i = 0)
// т.е. для i от 0 до (n-1) включительно
// т.е. i увеличивается от итерации к итерации на единичку (i = i + 1)
String word = scanner.nextLine(); // считали очередное слово
words[i] = word; // сохранили его в массив
}
int counter = 10; // завели переменную счетчик
while (counter > 0) { // пока это условие выполняется (т.е. пока значение переменной больше нуля) - будет выполняться код:
System.out.println(counter);
counter = counter - 1;
}
String[] someWords = {"even", "odd"}; // таким образом вы можете создать массив из заранее указанных элементов
int value = scanner.nextInt();
System.out.println("Value " + value + " is " + someWords[value % 2]);
while (true) { // выполняем цикл вечно (т.к. условие всегда верно)
int x = scanner.nextInt();
if (x % 2 == 0) { // все четные числа мы хотим игнорировать
continue; // эта команда говорит что мы не будем выполнять оставшийся код этой итерации цикла - а сразу перейдем к следующей (т.е. пойдем считывать следующее число)
}
System.out.println(x); // все остальные мы выводим
if (x == -1) { // как только вводится специальное число -1 - мы выходим из цикла
break; // эта команда заканчивает исполнение цикла и выполняется код сразу после фигурных скобок цикла
}
}
String a = "somespecialsecretpasswordthatonlyuserknowdoyouknowhowbeautifulareunicorns?";
String b = scanner.nextLine();
if (a.equals(b)) { // для сравнения строк надо использовать эту конструкцию, а не оператор ==
System.out.println("Строки совпали!");
} else {
System.out.println("Строки не совпали!");
}
Задание
Задание на уроке и затем дома - выполнить задачки (не обязательно все, понимаю что у вас есть и другие задания - сделайте сколько получится) в http://mdl.sch239.net/ :
1) Создайте массив из целых чисел 10, 20, 30, 40 и 50, посчитайте их сумму, выведите ее в консоль.
2) Создайте массив, считайте в него 5 вещественных чисел которые ввел пользователь. Посчитайте циклом for
их сумму и выведите ее.
3) Создайте массив, считайте в него 5 вещественных чисел которые ввел пользователь. Затем пробегите циклом for
по этим элементам чтобы посчитать и затем вывести их сумму, максимальное, минимальное и среднее значение.
4) Запросите у пользователя n
- сколько чисел он хочет ввести. Используя цикл for
считайте n
вещественных чисел которые ввел пользователь. Выведите их сумму, максимальное, минимальное и среднее значение.
5) Пользователь вводит номер дня недели (от 1 до 7). Выведите как на английском называется этот день (маленькими буквами, например monday, если не помните остальные - вбейте в гугл “дни недели на английском””). Если ввод неправильный - скажите об этом пользователю: Day should be from 1 to 7 inclusive!
. Пожалуйста используйте массив и цикл, а не семь if-else-ов.
6) Пользователь вводит день недели на англйиском. Выведите номер дня недели (от 1 до 7). Если ввод неправильный - выведите No such day! (ensure that you use lower case like 'monday')
. Пожалуйста используйте массив и цикл, а не семь if-else-ов.
7) Пользователь вводит число имен n
. Затем вводит эти имена один за другим (сначала первое, затем второе и т.д. до n
-ого). Затем вводит имя которое нужно найти. Выведите номер (нумерация с 1) первого имени из списка которое совпадает с введенным. Если не найдено - выведите Not found!
8) Пользователь вводит целые числа одно за другим. Напишите цикл while
. Если он введет число -1 - воспользуйтесь командой break
чтобы выйти из цикла. В конце выведите сумму всех чисел кроме -1
.
9) Пользователь вводит целые числа одно за другим. Напишите цикл while
. Если он введет число -1 - воспользуйтесь командой break
чтобы выйти из цикла. В конце выведите сумму всех чисел кратных 13 (остальные пропускайте с помощью команды continue
).
10) Считайте целое число n. Выведите числа от n до 1, после чего напишите “BOOM”. Используйте while
!
Возможные ошибки
1) Если вы видите что-то вроде /var/www/html/jobe/application/libraries/../../runguard/runguard: warning: timelimit exceeded
при отправке решения в mdl:
Система тестирования подвисла и не успела в рамках ограничения на время тестирования задания его проверить. При этом если вы повторно попробуете отправить задание - система ничего не сделает т.к. думает что раз решение не изменилось, то исход будет такой же.
Решение - добавить фиктивное изменение в код (например пустую строку) и переотправить.
2) Если вы видите что-то вроде NullPointerException
и ошибка указывает на строчку с первым обращение к массиву - возможно вы забыли его инициализировать (создать - выделить память для массива через ключевое слово new
)?
3) Если вы видите что-то вроде IndexOutOfBounds
и ошибка указывает на строчку с обращением к массиву по индексу - возможно вы обратились по индексу -1 или наоборот n
при том что это его размер? (индексация с нуля, поэтому максимальный индекс - n-1
, обратите внимание что ошибка указывает ошибочное значение индекса обращения)
4) Если вы видите что-то вроде InputMismatchException
и ошибка указывает на строчку scanner.nextDouble()
а вы уверены что к моменту выполнения считывания вещественного числа на вход программе дано число - попробуйте еще раз, но введя вещественное число через запятую, а не через точку.
Причина этой ошибки в том что в операционной системе компьютера есть понятие локаль - например она может быть русская, американская или еще какая-то. От нее зависит стандартный способ записи вещественных чисел - в русской локали это запятая, а в американской - через точку.
Подробнее (и про то как в программе фиксировать локаль чтобы она не зависила от компьютера на котором программа исполняется): https://stackoverflow.com/questions/5929120/nextdouble-throws-an-inputmismatchexception-when-i-enter-a-double (гуглится по InputMismatchException nextDouble
)