Към съдържанието
wannacode

Масиви

Проблем

Тридесет оценки

Учител пише програма за оценките от контролното. За петима ученици прави пет променливи:

int score1 = 62;
int score2 = 85;
int score3 = 47;
int score4 = 91;
int score5 = 78;
int sum = score1 + score2 + score3 + score4 + score5;
Console.WriteLine(sum);
Изход
363

В класа обаче са тридесет. Тридесет променливи, тридесет събираеми. А за най-високия резултат трябват още двадесет и девет сравнения. Цикълът от миналия урок не помага: той не може да мине през score1, score2, score3, защото това са отделни имена. Трябват ни много стойности под едно име.

Идеята

Масив: редица от кутийки

Масивът е редица от стойности от един тип под едно име. Всяка стойност, елемент на масива, има номер: индекс. Индексите започват от 0.

int[] scores = { 62, 85, 47, 91, 78 };
Console.WriteLine(scores[0]);
Console.WriteLine(scores[4]);
Console.WriteLine(scores.Length);
scores[2] = 50;
Console.WriteLine(scores[2]);
Изход
62
78
5
50
  • int[] е типът: „масив от int“. Стойностите са в { }.
  • scores[0] е първият елемент, scores[4] петият. Последният индекс е винаги с 1 по-малък от броя.
  • scores.Length е броят на елементите. Тук е 5.
  • scores[2] = 50; сменя един елемент. Останалите не се променят.

Ако още не знаеш стойностите, създаваш масива само с размер. Тогава всички елементи са 0:

int[] booked = new int[3];
booked[1] = 2;
Console.WriteLine(booked[0] + " " + booked[1] + " " + booked[2]);
Изход
0 2 0

Размерът се определя при създаването и после не се сменя.

По-точно, за любопитните
  • Индексите са само от 0 до броя минус 1. Отрицателен индекс е извън масива.

Пробвай

Кой е кой?

Какво ще отпечата програмата?

int[] prices = { 12, 7, 30, 5 };
Console.WriteLine(prices[1] + prices[3]);
Отговор

Идеята

Цикъл през масива

Сега цикълът вече помага. Броячът 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];
}
Console.WriteLine("Сума: " + sum);
Console.WriteLine("Средно: " + (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];
}
}
Console.WriteLine(max); // 91
Стъпка по стъпка, с думи
  1. Пет резултата, едно до друго. Номерата отдолу са индексите: от 0 до 4.
  2. max започва от първия: scores[0] е 62.
  3. i = 1: 85 > 62, max става 85.
  4. i = 2: 47 не е по-голямо от 85. Нищо не се сменя.
  5. i = 3: 91 > 85, max става 91.
  6. i = 4: 78 < 91. После i става 5, 5 < scores.Length е невярно и цикълът спира.
  7. Най-големият резултат е 91.

max започва от първия елемент, а не от 0. Ако всички резултати бяха отрицателни, 0 щеше да „спечели“, без да е в масива. Затова и цикълът започва от i = 1: първият вече е в max.

Пробвай

Намери грешката

Програмата трябва да отпечата сумата 363. Вместо това спира с грешка:

Грешка
Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.

На кой ред е грешката?

Избери реда с грешката.

Идеята

foreach: за всеки елемент

Когато ти трябват само стойностите, а не индексите, има по-кратък цикъл. Колко ученици са взели изпита (60 точки и нагоре)?

int[] scores = { 62, 85, 47, 91, 78 };
int passed = 0;
foreach (int score in scores)
{
if (score >= 60)
{
passed++;
}
}
Console.WriteLine("Взели изпита: " + passed);
Изход
Взели изпита: 4

Чете се „за всяко score от scores“. Той се казва foreach. Няма брояч и индекс, затова не можеш да излезеш извън масива.

Има и граница: не знаеш на кой индекс си и не можеш да смениш елемента.

По-точно, за любопитните
  • Ако напишеш score = 0; в тялото, програмата не се компилира: променливата на foreach е само за четене.
  • За да смениш елементи или да ти трябва индексът (например за съседа scores[i + 1]), ползвай обикновен for.

Пробвай

Две имена, един масив

Какво ще отпечата програмата?

int[] prices = { 10, 20, 30 };
int[] sale = prices;
sale[0] = 5;
Console.WriteLine(prices[0]);
Отговор
По-точно, за любопитните

Истинско копие правиш с нов масив и цикъл:

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;
Console.WriteLine(prices[0] + " " + sale[0]);
Изход
10 5

Същото дава и (int[])prices.Clone().

Пробвай

Подреди редовете

Програмата трябва да намери най-ниската цена. Подреди редовете ѝ.

  1. min = prices[i];
  2. Console.WriteLine(min);
  3. }
  4. int min = prices[0];
  5. int[] prices = { 18, 7, 25, 12 };
  6. {
  7. {
  8. for (int i = 1; i < prices.Length; i++)
  9. if (prices[i] < min)
  10. }

Упражнение

Сметки с масив

Реши задачите в редактора си. Всяка програма първо чете колко са числата, после самите числа, по едно на ред:

int n = int.Parse(Console.ReadLine());
int[] numbers = new int[n];
for (int i = 0; i < n; i++)
{
numbers[i] = int.Parse(Console.ReadLine());
}

1. Сума, четни, нечетни. Отпечатай сумата на всички числа, на четните и на нечетните.

Вход
3
1
2
3
Изход
Сума: 6
Четни: 2
Нечетни: 4

2. Обратно. Създай нов масив със същите числа в обратен ред и го отпечатай на един ред.

Вход
5
1
2
3
4
5
Изход
5 4 3 2 1

3. Най-малко, най-голямо, средно. С едно минаване през масива.

Вход
5
4
9
2
7
4
Изход
Най-малко: 2
Най-голямо: 9
Средно: 5.2

Упражнение

Подреждане и броене

4. Сортиране. Подреди числата от най-малкото към най-голямото. Подсказка: минавай през масива и ако два съседа са в грешен ред, разменяй ги (размяната е от урока за променливите). Повтори, докато няма какво да размениш. Това се казва метод на мехурчето: големите числа „изплуват“ към края.

Вход
5
42
7
19
3
25
Изход
3 7 19 25 42

5. Най-дълга поредица. Намери най-дългата поредица от еднакви числа едно след друго.

Вход
8
2
2
5
5
5
1
5
5
Изход
Числото 5, 3 пъти подред

6. Статистика на оценките. Прочети оценки от 2 до 6 и отпечатай колко са от всеки вид. Подсказка: масив counts с 7 елемента, в който оценката е индексът: counts[grade]++.

Вход
8
6
4
5
6
3
2
6
5
Изход
Отличен (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". Докато числото е поне колкото текущата стойност, добавяй знака и вади стойността.

Тест

Провери се

1. В масива { 62, 85, 47, 91, 78 } на кой индекс е 91?
2. Кой е индексът на последния елемент на масива scores?
3. Какво има в масива веднага след int[] booked = new int[3];?
4. Цикълът е for (int i = 0; i <= scores.Length; i++) и чете scores[i]. Какво става?
5. int[] sale = prices; sale[0] = 5; Какво става с prices[0]?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·