Масиви
Проблем
Тридесет оценки
Учител пише програма за оценките от контролното. За петима ученици прави пет променливи:
int score1 = 62;int score2 = 85;int score3 = 47;int score4 = 91;int score5 = 78;int sum = score1 + score2 + score3 + score4 + score5;System.out.println(sum);363В класа обаче са тридесет. Тридесет променливи, тридесет събираеми. А за най-високия резултат трябват още двадесет и девет сравнения. Цикълът от миналия урок не помага: той не може да мине през score1, score2, score3, защото това са отделни имена. Трябват ни много стойности под едно име.
Идеята
Масив: редица от кутийки
Масивът е редица от стойности от един тип под едно име. Всяка стойност, елемент на масива, има номер: индекс. Индексите започват от 0.
int[] scores = { 62, 85, 47, 91, 78 };System.out.println(scores[0]);System.out.println(scores[4]);System.out.println(scores.length);scores[2] = 50;System.out.println(scores[2]);6278550int[]е типът: „масив отint“. Стойностите са в{ }.
scores[0]е първият елемент,scores[4]петият. Последният индекс е винаги с 1 по-малък от броя.scores.lengthе броят на елементите. Тук е 5.scores[2] = 50;сменя един елемент. Останалите не се променят.
Ако още не знаеш стойностите, създаваш масива само с размер. Тогава всички елементи са 0:
int[] booked = new int[3];booked[1] = 2;System.out.println(booked[0] + " " + booked[1] + " " + booked[2]);0 2 0Размерът се определя при създаването и после не се сменя.
По-точно, за любопитните
- Индексите са само от 0 до броя минус 1. Отрицателен индекс е извън масива.
Пробвай
Кой е кой?
Какво ще отпечата програмата?
int[] prices = { 12, 7, 30, 5 };System.out.println(prices[1] + prices[3]);Броим от 0: prices[1] е 7 (вторият), prices[3] е 5 (четвъртият). 7 + 5 = 12. Ако броиш от 1, ще вземеш 12 и 30.
Идеята
Цикъл през масива
Сега цикълът вече помага. Броячът i става индексът: минава от 0 до последния и на всеки кръг взима scores[i].
int[] scores = { 62, 85, 47, 91, 78 };int sum = 0;for (int i = 0; i < scores.length; i++) { sum += scores[i];}System.out.println("Сума: " + sum);System.out.println("Средно: " + (double) sum / scores.length);Сума: 363Средно: 72.6Условието е i < scores.length, а не число. Добавиш ли тридесетте оценки в { }, цикълът не се променя. Това се казва обхождане на масива.
(double) е нужно заради целочисленото деление: 363 / 5 е 72, а ни трябва 72,6.
Виж го
Най-високият резултат
Как намираш най-голямото число? Помниш най-голямото засега и го сменяш, щом видиш по-голямо.
int[] scores = { 62, 85, 47, 91, 78 };int max = scores[0];for (int i = 1; i < scores.length; i++) { if (scores[i] > max) { max = scores[i]; }}System.out.println(max); // 91Стъпка по стъпка, с думи
- Пет резултата, едно до друго. Номерата отдолу са индексите: от 0 до 4.
- max започва от първия: scores[0] е 62.
- i = 1: 85 > 62, max става 85.
- i = 2: 47 не е по-голямо от 85. Нищо не се сменя.
- i = 3: 91 > 85, max става 91.
- i = 4: 78 < 91. После i става 5, 5 < scores.length е невярно и цикълът спира.
- Най-големият резултат е 91.
max започва от първия елемент, а не от 0. Ако всички резултати бяха отрицателни, 0 щеше да „спечели“, без да е в масива. Затова и цикълът започва от i = 1: първият вече е в max.
Пробвай
Намери грешката
Програмата трябва да отпечата сумата 363. Вместо това спира с грешка:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5На кой ред е грешката?
Избери реда с грешката.
<= цикълът прави още един кръг, с i = 5. Индексите на масива с 5 елемента са от 0 до 4, елемент scores[5] няма. Програмата не чете чужда памет, а спира с грешка. Това се казва излизане извън масива. Поправката е i < scores.length.Идеята
for-each: за всеки елемент
Когато ти трябват само стойностите, а не индексите, има по-кратък цикъл. Колко ученици са взели изпита (60 точки и нагоре)?
int[] scores = { 62, 85, 47, 91, 78 };int passed = 0;for (int score : scores) { if (score >= 60) { passed++; }}System.out.println("Взели изпита: " + passed);Взели изпита: 4Чете се „за всяко score от scores“. Той се казва for-each. Няма брояч и индекс, затова не можеш да излезеш извън масива.
Има и граница: не знаеш на кой индекс си и не можеш да смениш елемента.
По-точно, за любопитните
- Ако напишеш
score = 0;в тялото, сменяш само копието вscore. Масивът остава същият. Компилаторът не те спира.
- За да смениш елементи или да ти трябва индексът (например за съседа
scores[i + 1]), ползвай обикновенfor.
Пробвай
Две имена, един масив
Какво ще отпечата програмата?
int[] prices = { 10, 20, 30 };int[] sale = prices;sale[0] = 5;System.out.println(prices[0]);int b = a; копира стойността. При масивите не е така: sale = prices не прави нов масив, а дава второ име на същия. Затова промяната през sale се вижда и през prices. Защо е така, ще разберем в модул „Класове и обекти“: масивът е обект, а променливата пази къде се намира той.По-точно, за любопитните
Истинско копие правиш с нов масив и цикъл:
int[] prices = { 10, 20, 30 };int[] sale = new int[prices.length];for (int i = 0; i < prices.length; i++) { sale[i] = prices[i];}sale[0] = 5;System.out.println(prices[0] + " " + sale[0]);10 5Същото дава и prices.clone().
Пробвай
Подреди редовете
Програмата трябва да намери най-ниската цена. Подреди редовете ѝ.
int[] prices = { 18, 7, 25, 12 };for (int i = 1; i < prices.length; i++) {}if (prices[i] < min) {min = prices[i];int min = prices[0];}System.out.println(min);
Упражнение
Сметки с масив
Реши задачите в редактора си. Всяка програма първо чете колко са числата, после самите числа, по едно на ред:
Scanner in = new Scanner(System.in);int n = in.nextInt();int[] numbers = new int[n];for (int i = 0; i < n; i++) { numbers[i] = in.nextInt();}1. Сума, четни, нечетни. Отпечатай сумата на всички числа, на четните и на нечетните.
3123Сума: 6Четни: 2Нечетни: 42. Обратно. Създай нов масив със същите числа в обратен ред и го отпечатай на един ред.
5123455 4 3 2 13. Най-малко, най-голямо, средно. С едно минаване през масива.
549274Най-малко: 2Най-голямо: 9Средно: 5.2Упражнение
Подреждане и броене
4. Сортиране. Подреди числата от най-малкото към най-голямото. Подсказка: минавай през масива и ако два съседа са в грешен ред, разменяй ги (размяната е от урока за променливите). Повтори, докато няма какво да размениш. Това се казва метод на мехурчето: големите числа „изплуват“ към края.
5427193253 7 19 25 425. Най-дълга поредица. Намери най-дългата поредица от еднакви числа едно след друго.
822555155Числото 5, 3 пъти подред6. Статистика на оценките. Прочети оценки от 2 до 6 и отпечатай колко са от всеки вид. Подсказка: масив counts с 7 елемента, в който оценката е индексът: counts[grade]++.
864563265Отличен (6): 3Много добър (5): 2Добър (4): 1Среден (3): 1Слаб (2): 1Още задачи
- Медиана. Числото по средата на сортирания масив. За 3, 1, 4, 1, 5 медианата е 3. Ако числата са четен брой, медианата е средното на двете в средата: за 7, 1, 3, 9 е (3 + 7) / 2 = 5.
- Симетричен масив. Чете ли се еднакво отпред назад и отзад напред? 1 2 3 2 1 е симетричен, 1 2 3 1 не е.
- Римски цифри. Прочети число от 1 до 3999 и го отпечатай с римски цифри: 2024 е MMXXIV, 1994 е MCMXCIV. Подсказка: два масива един до друг, със стойностите
1000, 900, 500, 400, 100, …, 1и със знаците"M", "CM", "D", "CD", "C", …, "I". Докато числото е поне колкото текущата стойност, добавяй знака и вади стойността.
Тест