Tablice jednowymiarowe
W poprzednich lekcjach każda wartość potrzebowała własnej zmiennej — przy trzech produktach było to męczące, przy trzydziestu byłoby niemożliwe. Tablica to jedna nazwa dla wielu wartości tego samego typu. Dopiero teraz pętle pokażą, do czego naprawdę służą.
Czego się dziś nauczysz
- Utworzysz tablicę i wypełnisz ją wartościami na trzy różne sposoby
- Odczytasz i zmienisz dowolny element po jego numerze
- Przejdziesz całą tablicę pętlą
fori pętląforeach - Policzysz sumę, średnią, minimum i maksimum z zawartości tablicy
- Wyjaśnisz, dlaczego przypisanie tablicy do drugiej zmiennej nie tworzy kopii
Czym jest tablica
Wyobraź sobie szafkę z ponumerowanymi szufladami. Szafka ma jedną nazwę, a każda szuflada — swój numer. Wszystkie szuflady są tej samej wielkości i mieszczą ten sam rodzaj rzeczy. Ich liczba jest ustalana przy stawianiu szafki i już się nie zmieni.
To dokładnie tablica. Zamiast pisać:
int ocena1 = 4;
int ocena2 = 5;
int ocena3 = 3;
int ocena4 = 5;
int ocena5 = 2;
int suma = ocena1 + ocena2 + ocena3 + ocena4 + ocena5;
piszemy:
int[] oceny = { 4, 5, 3, 5, 2 };
int suma = 0;
for (int i = 0; i < oceny.Length; i++)
{
suma += oceny[i];
}
Największa zaleta widać dopiero przy zmianie
Wersja pierwsza przy dziesięciu ocenach wymaga dopisania pięciu zmiennych i pięciu składników w sumie. Wersja druga — zmiany jednej liczby w nawiasach klamrowych. Reszta kodu zostaje bez zmian, bo pętla sama sprawdza, ile jest elementów.
| Cecha tablicy | Znaczenie |
|---|---|
| jeden typ | Wszystkie elementy są tego samego typu. Tablica int[] mieści tylko liczby całkowite. |
| stały rozmiar | Liczba elementów jest ustalana przy tworzeniu i nie da się jej zmienić. Do list rosnących służy typ List<T> z bloku o C# nowoczesnym. |
| numerowanie od zera | Pierwszy element ma numer 0, ostatni — Length - 1. |
| dostęp po numerze | oceny[2] to trzeci element. Odczyt jest natychmiastowy, niezależnie od wielkości tablicy. |
Trzy sposoby utworzenia tablicy
// 1. pusta tablica o zadanym rozmiarze
int[] punkty = new int[5]; // piec elementow, kazdy rowny 0
// 2. z podanymi wartosciami - rozmiar wyliczy kompilator
int[] oceny = { 4, 5, 3, 5, 2 }; // piec elementow
// 3. zapis pelny - to samo, tylko dluzej
int[] wyniki = new int[] { 10, 20, 30 };
| Sposób | Kiedy stosować |
|---|---|
new int[5] |
Gdy znasz rozmiar, ale nie znasz jeszcze wartości — np. zaraz wypełnisz tablicę danymi od użytkownika. Wszystkie elementy dostają wartość domyślną. |
{ 4, 5, 3 } |
Gdy znasz wartości. Najkrótszy i najczytelniejszy zapis. Uwaga: działa tylko przy deklaracji zmiennej. |
new int[] { ... } |
Ten sam efekt, ale zapis działa też poza deklaracją — np. przy przekazywaniu tablicy do metody. |
Wartości domyślne
Świeżo utworzona tablica nie jest pusta — każdy element ma wartość domyślną swojego typu, tę samą, którą poznałeś przy typach prostych:
| Typ tablicy | Wartość domyślna | Uwagi |
|---|---|---|
int[], long[] | 0 | |
double[], decimal[] | 0 | |
bool[] | false | |
char[] | znak o kodzie 0 | Niewidoczny — na ekranie wygląda jak nic. |
string[] | brak wartości | Nie pusty napis! Próba użycia takiego elementu przerywa program. Trzeba go najpierw czymś wypełnić. |
Pusta tablica napisów to pułapka
string[] imiona = new string[3]; tworzy trzy „puste szuflady”, ale nie ma w nich pustych napisów — nie ma w nich nic. Wywołanie imiona[0].Length przerwie program błędem NullReferenceException. Jeśli chcesz mieć puste napisy, wypełnij tablicę: Array.Fill(imiona, "");.
Indeksy i Length
Element wskazujemy jego numerem w nawiasach kwadratowych. Numerowanie zaczyna się od zera — to nie jest kaprys, tylko konwencja większości języków programowania i trzeba się do niej przyzwyczaić.
int[] oceny = { 4, 5, 3, 5, 2 };
Console.WriteLine(oceny[0]); // 4 - pierwszy element
Console.WriteLine(oceny[2]); // 3 - trzeci element
Console.WriteLine(oceny.Length); // 5 - ile elementow
Console.WriteLine(oceny[oceny.Length - 1]); // 2 - ostatni element
oceny[4] = 6; // zmiana ostatniego elementu
Console.WriteLine(oceny[4]); // 6
4
3
5
2
6
| Indeks | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| Wartość | 4 | 5 | 3 | 5 | 2 |
| Nazwa | oceny[0] | oceny[1] | oceny[2] | oceny[3] | oceny[4] |
Length to właściwość, nie metoda
Piszemy oceny.Length bez nawiasów. Nawiasy — oceny.Length() — to błąd CS1955. Dla napisów jest tak samo: tekst.Length. Zapamiętaj tę różnicę, bo w innych językach (na przykład w Javie) tablica ma length małą literą, a napis ma metodę length() z nawiasami.
Ostatni element to zawsze Length - 1
Tablica pięcioelementowa ma indeksy od 0 do 4. Ta „jedynka mniej” jest źródłem tylu błędów, że warto ją sobie powtórzyć na głos. Za chwilę poznasz krótszy zapis: oceny[^1].
Wyjście poza zakres
Odwołanie do nieistniejącego elementu nie jest błędem kompilacji — kompilator zwykle nie wie, jaki numer będzie w zmiennej. Program uruchamia się normalnie i przerywa działanie dopiero w tym miejscu:
int[] oceny = { 4, 5, 3, 5, 2 };
Console.WriteLine(oceny[5]); // Index was outside the bounds of the array.
Unhandled exception. System.IndexOutOfRangeException:
Index was outside the bounds of the array.
Trzy najczęstsze przyczyny tego błędu:
| Zapis | Problem |
|---|---|
for (int i = 1; i <= n.Length; i++) | Zaczyna od 1 i kończy na Length — pomija pierwszy element i wychodzi poza ostatni. Poprawnie: i = 0 i i < n.Length. |
for (int i = 0; i <= n.Length; i++) | Jeden obieg za dużo. Znak musi być <, nie <=. |
n[numerOdUzytkownika] | Użytkownik wpisał 7, a tablica ma 5 elementów. Zawsze sprawdzaj numer przed użyciem. |
int[] oceny = { 4, 5, 3, 5, 2 };
Console.Write($"Numer oceny (0-{oceny.Length - 1}): ");
bool ok = int.TryParse(Console.ReadLine(), out int numer);
if (!ok || numer < 0 || numer >= oceny.Length)
{
Console.WriteLine("Nie ma takiej oceny.");
}
else
{
Console.WriteLine($"Ocena numer {numer} to {oceny[numer]}.");
}
Warunek numer < 0 || numer >= oceny.Length to gotowa formułka na sprawdzenie indeksu. Warto ją zapamiętać — będzie wracać w każdym programie z tablicami.
Tablica i pętle
Tablice i pętle to para nierozłączna. Są dwa sposoby przejścia całej tablicy i każdy ma swoje miejsce.
Pętla for — gdy potrzebny jest numer
int[] oceny = { 4, 5, 3, 5, 2 };
for (int i = 0; i < oceny.Length; i++)
{
Console.WriteLine($"Ocena numer {i + 1}: {oceny[i]}");
}
Ocena numer 1: 4
Ocena numer 2: 5
Ocena numer 3: 3
Ocena numer 4: 5
Ocena numer 5: 2
Nagłówek for (int i = 0; i < tablica.Length; i++) to najczęstsza linia w programach na tablicach. Napisz ją kilkanaście razy, a wejdzie w palce.
Dlaczego {i + 1} w komunikacie
Program liczy od zera, człowiek od jedynki. Wewnątrz kodu używamy indeksu i, a użytkownikowi pokazujemy i + 1. To drobiazg, który odróżnia program przyjazny od dziwacznego.
Pętla foreach — gdy numer jest zbędny
int[] oceny = { 4, 5, 3, 5, 2 };
int suma = 0;
foreach (int ocena in oceny)
{
suma += ocena;
}
Console.WriteLine($"Suma: {suma}");
Czyta się to prawie po polsku: „dla każdej oceny w ocenach”. Nie ma licznika, więc nie ma jak się pomylić o jeden ani wyjść poza zakres.
| Kryterium | for | foreach |
|---|---|---|
| Znasz numer elementu | tak | nie |
| Możesz zmieniać elementy | tak | nie |
| Możesz iść co drugi albo od końca | tak | nie |
| Ryzyko pomyłki o jeden | jest | nie ma |
| Typowe zastosowanie | wypełnianie, modyfikowanie, porównywanie sąsiadów | sumowanie, wypisywanie, wyszukiwanie |
foreach nie zmienia zawartości tablicy
Zmienna pętli foreach to kopia elementu. Przypisanie do niej niczego nie zmieni w tablicy — a w C# jest nawet zabronione i kończy się błędem kompilacji CS1656. Do modyfikowania służy for.
foreach (int ocena in oceny)
{
ocena = ocena + 1; // BLAD CS1656: nie mozna przypisac do zmiennej petli
}
for (int i = 0; i < oceny.Length; i++)
{
oceny[i] = oceny[i] + 1; // OK - to dziala
}
Indeksy od końca i zakresy
Od C# 8 istnieje krótszy zapis dla „liczone od końca”. Znak ^ (daszek) oznacza „tyle od tyłu”:
int[] liczby = { 10, 20, 30, 40, 50 };
Console.WriteLine(liczby[^1]); // 50 - ostatni (to samo co liczby[liczby.Length - 1])
Console.WriteLine(liczby[^2]); // 40 - przedostatni
int[] srodek = liczby[1..4]; // elementy o indeksach 1, 2, 3
int[] poczatek = liczby[..2]; // od poczatku do indeksu 2 (bez niego)
int[] koniec = liczby[3..]; // od indeksu 3 do konca
Console.WriteLine(string.Join(", ", srodek));
Console.WriteLine(string.Join(", ", poczatek));
Console.WriteLine(string.Join(", ", koniec));
50
40
20, 30, 40
10, 20
40, 50
Górna granica zakresu jest wyłączna
liczby[1..4] daje elementy 1, 2 i 3 — czwórka jest granicą, a nie ostatnim zabranym elementem. To ta sama reguła co przy Random.Next(1, 101) z lekcji 16 i przy pętli for (i = 0; i < Length; i++). W C# „do” prawie zawsze znaczy „przed”.
^1 to ostatni, nie ^0
Indeksy od przodu zaczynają się od zera, od tyłu — od jedynki. Wygląda to niekonsekwentnie, ale ma sens: liczby[^0] byłoby elementem za ostatnim, czyli poza tablicą. Zapamiętaj: ^1 to ostatni.
Wycinek liczby[1..4] tworzy nową tablicę z kopiami elementów. Zmiana w wycinku nie wpłynie na oryginał — w przeciwieństwie do zwykłego przypisania, o którym za chwilę.
Tablica jest referencją
To jedna z najważniejszych rzeczy w tej lekcji i pierwsza okazja, żeby zobaczyć różnicę między typem wartościowym a referencyjnym.
// typ wartosciowy - kopiuje sie wartosc
int a = 5;
int b = a;
b = 99;
Console.WriteLine($"a = {a}, b = {b}"); // a = 5, b = 99
// typ referencyjny - kopiuje sie ADRES
int[] x = { 1, 2, 3 };
int[] y = x;
y[0] = 99;
Console.WriteLine($"x[0] = {x[0]}, y[0] = {y[0]}"); // OBA po 99!
a = 5, b = 99
x[0] = 99, y[0] = 99
Zmienna tablicowa nie zawiera elementów — zawiera adres miejsca, w którym one leżą. Przypisanie y = x kopiuje ten adres, więc obie zmienne pokazują na tę samą szafkę. To jak dorobienie drugiego klucza, a nie postawienie drugiej szafki.
Jak zrobić prawdziwą kopię
int[] oryginal = { 1, 2, 3 };
// sposob 1: wycinek calosci
int[] kopia1 = oryginal[..];
// sposob 2: metoda Clone (wymaga rzutowania)
int[] kopia2 = (int[])oryginal.Clone();
// sposob 3: recznie, petla
int[] kopia3 = new int[oryginal.Length];
for (int i = 0; i < oryginal.Length; i++)
{
kopia3[i] = oryginal[i];
}
kopia1[0] = 99;
Console.WriteLine($"oryginal[0] = {oryginal[0]}"); // nadal 1
oryginal[0] = 1
Ta sama zasada dotyczy porównywania
if (x == y) dla tablic sprawdza, czy to ta sama tablica, a nie czy mają tę samą zawartość. Dwie osobne tablice o identycznych wartościach dadzą false. Do porównania zawartości trzeba przejść je pętlą albo użyć gotowej metody — pokażemy ją w następnej lekcji.
Użyte w tej lekcji elementy
| Nazwa | Zwraca | Działanie |
|---|---|---|
tablica.Length | int |
Właściwość (bez nawiasów) — liczba elementów. Ustalana przy tworzeniu i niezmienna. |
tablica[i] | element | Odczyt lub zapis elementu o numerze i. Numer poza zakresem przerywa program. |
tablica[^i] | element | Element liczony od końca; ^1 to ostatni. |
tablica[a..b] | tablica | Nowa tablica z elementami od a do b (bez b). Zapis [..] daje kopię całości. |
string.Join(sep, tab) | string |
Skleja elementy w jeden napis, wstawiając między nie separator: string.Join(", ", oceny) daje "4, 5, 3, 5, 2". Najwygodniejszy sposób wypisania całej tablicy. |
tablica.Clone() | object |
Kopia tablicy. Wynik trzeba rzutować: (int[])oceny.Clone(). |
Array.Fill(tab, w) | nic | Wypełnia całą tablicę podaną wartością. Przydatne zwłaszcza dla string[], żeby uniknąć pustych elementów. |
Math.Round(x, n) | double |
Zaokrąglenie wartości — używane przy średnich. Pamiętaj o regule połówek z lekcji 13. |
Klasa Array ma tego znacznie więcej
Array.Sort, Array.Reverse, Array.IndexOf, Array.Resize — cała następna lekcja jest o gotowych metodach do tablic. W tej lekcji celowo robimy wszystko ręcznie, żebyś rozumiał, co te metody wykonują za ciebie.
Dziennik ocen
Program wczytuje oceny do tablicy, a potem wylicza z nich komplet statystyk. To wzorzec, który przewija się przez cały blok o tablicach.
const int IleOcen = 6;
int[] oceny = new int[IleOcen];
Console.WriteLine("=== DZIENNIK OCEN ===");
Console.WriteLine();
// --- 1. wypelnienie tablicy z walidacja ---
for (int i = 0; i < oceny.Length; i++)
{
bool poprawna;
do
{
Console.Write($"Ocena {i + 1} z {oceny.Length} (1-6): ");
bool ok = int.TryParse(Console.ReadLine(), out int wpis);
poprawna = ok && wpis >= 1 && wpis <= 6;
if (poprawna)
{
oceny[i] = wpis;
}
else
{
Console.WriteLine(" Ocena musi byc liczba od 1 do 6.");
}
}
while (!poprawna);
}
// --- 2. jedno przejscie, cztery wyniki ---
int suma = 0;
int najnizsza = oceny[0];
int najwyzsza = oceny[0];
foreach (int ocena in oceny)
{
suma += ocena;
if (ocena < najnizsza) { najnizsza = ocena; }
if (ocena > najwyzsza) { najwyzsza = ocena; }
}
double srednia = (double)suma / oceny.Length;
// --- 3. drugie przejscie: ile powyzej sredniej ---
int powyzej = 0;
foreach (int ocena in oceny)
{
if (ocena > srednia)
{
powyzej++;
}
}
// --- 4. wypisanie ---
Console.WriteLine();
Console.WriteLine("Wprowadzone oceny:");
for (int i = 0; i < oceny.Length; i++)
{
Console.WriteLine($" [{i}] = {oceny[i]} {new string('*', oceny[i])}");
}
Console.WriteLine();
Console.WriteLine($"{"Suma:",-18}{suma,6}");
Console.WriteLine($"{"Srednia:",-18}{srednia,6:F2}");
Console.WriteLine($"{"Najnizsza:",-18}{najnizsza,6}");
Console.WriteLine($"{"Najwyzsza:",-18}{najwyzsza,6}");
Console.WriteLine($"{"Powyzej sredniej:",-18}{powyzej,6}");
Console.WriteLine();
Console.WriteLine($"Wszystkie: {string.Join(", ", oceny)}");
=== DZIENNIK OCEN ===
Ocena 1 z 6 (1-6): 4
Ocena 2 z 6 (1-6): 5
Ocena 3 z 6 (1-6): 3
Ocena 4 z 6 (1-6): 5
Ocena 5 z 6 (1-6): 2
Ocena 6 z 6 (1-6): 6
Wprowadzone oceny:
[0] = 4 ****
[1] = 5 *****
[2] = 3 ***
[3] = 5 *****
[4] = 2 **
[5] = 6 ******
Suma: 25
Srednia: 4,17
Najnizsza: 2
Najwyzsza: 6
Powyzej sredniej: 3
Wszystkie: 4, 5, 3, 5, 2, 6
Omówienie
| Fragment | Co robi i dlaczego tak |
|---|---|
new int[IleOcen] |
Rozmiar bierzemy ze stałej, a nie wpisujemy szóstki w trzech miejscach. Zmiana liczby ocen to poprawka jednej linii. |
do-while wewnątrz for |
Pętla zewnętrzna przechodzi po komórkach tablicy, wewnętrzna pilnuje, żeby do każdej trafiła sensowna wartość. Wzorzec walidacji z lekcji 16, tym razem powtórzony dla każdego elementu. |
oceny[i] = wpis; |
Do tablicy trafia wartość dopiero po sprawdzeniu. Zapisanie od razu wyniku TryParse wstawiłoby tam zero po każdej pomyłce. |
najnizsza = oceny[0]; |
Pierwszy element jako punkt startowy — to samo, co w zadaniu ze statystyką z lekcji 16. Start od zera dałby zawsze zero jako minimum, bo oceny są dodatnie. |
| suma, minimum i maksimum w jednej pętli | Trzy wyniki z jednego przejścia. Trzy osobne pętle dałyby ten sam wynik, ale trzykrotnie więcej pracy — przy sześciu ocenach bez znaczenia, przy milionie rekordów już nie. |
| drugie przejście po średniej | Tego akurat nie da się połączyć z pierwszym: żeby porównać ocenę ze średnią, trzeba już znać średnią, a ta jest znana dopiero po zsumowaniu wszystkiego. Klasyczny przypadek, w którym drugie przejście jest konieczne. |
(double)suma / oceny.Length |
Rzutowanie przed dzieleniem. Bez niego 25 / 6 dałoby 4 zamiast 4,1666… |
new string('*', oceny[i]) |
Prosty wykres słupkowy: tyle gwiazdek, ile wynosi ocena. Jedna linia zamiast pętli wewnętrznej. |
string.Join(", ", oceny) |
Cała tablica w jednej linii, z przecinkami. Zwróć uwagę, że metoda sama radzi sobie z ostatnim elementem — nie ma przecinka na końcu. |
Sprawdź rachunek
4 + 5 + 3 + 5 + 2 + 6 = 25, średnia 25 / 6 = 4,1666… → po zaokrągleniu do dwóch miejsc 4,17. Powyżej średniej są trzy oceny: 5, 5 i 6 — czwórka jest poniżej, bo 4 < 4,1666. To dobra okazja, żeby pokazać uczniom, dlaczego porównujemy z pełną wartością średniej, a nie z zaokrągloną.
Na czym się najczęściej potykamy
| Błąd | Co się dzieje i jak poprawić |
|---|---|
i <= tablica.Length |
IndexOutOfRangeException w ostatnim obiegu. Warunek to zawsze i < tablica.Length. |
tablica.Length() |
CS1955 — Length to właściwość, bez nawiasów. |
int[5] oceny; |
Rozmiar nie należy do nazwy zmiennej. Poprawnie: int[] oceny = new int[5];. |
int[] a; a[0] = 1; |
Sama deklaracja nie tworzy tablicy — nie ma jeszcze żadnych szuflad. Potrzebne new int[n] albo lista wartości. |
| zmiana rozmiaru tablicy | Nie da się. Array.Resize w rzeczywistości tworzy nową tablicę i przepisuje zawartość. Gdy rozmiar ma rosnąć, właściwym narzędziem jest List<T>. |
| przypisanie zamiast kopii | y = x nie kopiuje tablicy, tylko adres. Zmiana przez y widać przez x. Kopia: x[..] albo (int[])x.Clone(). |
x == y dla tablic |
Porównuje adresy, nie zawartość. Dwie różne tablice o tych samych liczbach dają false. |
zmiana elementu w foreach |
CS1656. Do modyfikowania używaj for. |
string[] bez wypełnienia |
NullReferenceException przy pierwszym użyciu elementu. Wypełnij: Array.Fill(tab, ""). |
| minimum startujące od zera | Dla samych liczb dodatnich wynikiem zawsze będzie zero. Zaczynaj od tablica[0]. |
| szukanie w pustej tablicy | tablica[0] na tablicy o rozmiarze 0 przerywa program. Gdy rozmiar może być zerowy, sprawdź go najpierw. |
Tablica jako argument metody
W lekcji 20 sprawdziłeś, że metoda dostaje kopię przekazanej wartości. Z tablicą jest inaczej — i to jedno z najczęstszych zaskoczeń w całym kursie.
static void Zmien(int liczba, int[] dane)
{
liczba = 99; // zmienia lokalna KOPIE liczby
dane[0] = 99; // zmienia element WSPOLNEJ tablicy
}
static void Main()
{
int punkty = 5;
int[] wyniki = { 5, 6, 7 };
Zmien(punkty, wyniki);
Console.WriteLine(punkty); // 5 - bez zmian
Console.WriteLine(wyniki[0]); // 99 - zmienione!
}
Nazwa tablicy nie przechowuje jej zawartości, tylko adres miejsca, w którym zawartość leży. Metoda dostaje kopię tego adresu — czyli wskazanie na tę samą tablicę. Zmiana elementu jest więc widoczna na zewnątrz.
Podmiana całej tablicy to co innego
Gdyby w metodzie napisać dane = new int[] { 1, 2 };, zmieniłby się sam parametr — lokalna kopia adresu — a zmienna wyniki w Main wskazywałaby dalej starą tablicę. Żeby podmienić także ją, trzeba użyć ref int[] dane. Do tego rozróżnienia wrócimy przy obiektach w lekcji 43.
Dowolna liczba argumentów: params
Skoro metoda może przyjąć tablicę, może też przyjąć „dowolnie wiele wartości” — słowo params pakuje je w tablicę za ciebie.
static int Suma(params int[] liczby)
{
int suma = 0;
for (int i = 0; i < liczby.Length; i++)
{
suma += liczby[i];
}
return suma;
}
Console.WriteLine(Suma(1, 2, 3)); // 6 - bez tworzenia tablicy
Console.WriteLine(Suma(5)); // 5
Console.WriteLine(Suma()); // 0 - zero argumentow tez wolno
Console.WriteLine(Suma(new int[] { 4, 4 }));// 8 - tablica tez pasuje
Dwie zasady params
Parametr z params musi być ostatni na liście i może być tylko jeden. Znasz to z biblioteki: string.Format i Console.WriteLine z wieloma argumentami działają właśnie tak.
Zadania
Utwórz tablicę dziesięcioelementową i wypełnij ją kwadratami kolejnych liczb od 1 do 10, po czym wypisz jej zawartość w jednej linii.
Wypisz zawartość tablicy w odwrotnej kolejności — bez zmieniania samej tablicy. Następnie utwórz nową tablicę zawierającą te elementy w odwróconej kolejności.
Wczytaj szukaną liczbę i sprawdź, czy występuje w tablicy. Podaj indeks pierwszego wystąpienia oraz łączną liczbę wystąpień.
Mając tablicę liczb, utwórz dwie nowe tablice: jedną z liczbami parzystymi, drugą z nieparzystymi. Pamiętaj, że rozmiar tablicy trzeba znać przed jej utworzeniem.
Wykonaj 1000 losowań kostką sześcienną i policz, ile razy wypadła każda ścianka. Wyniki przedstaw w tabeli razem z udziałem procentowym i słupkiem z gwiazdek.
Mając tablicę siedmiu temperatur (jeden tydzień), wypisz: średnią, dzień najcieplejszy i najzimniejszy (z nazwą dnia tygodnia), liczbę dni powyżej średniej oraz największy skok temperatury między kolejnymi dniami.
Co trzeba zapamiętać
- Tablica jest obiektem o stałej długości. List<T> z lekcji 31 wygodniej obsługuje dopisywanie danych.
- Indeksy zwykłej tablicy zaczynają się od 0 i kończą na Length – 1.
- Length jest właściwością odczytywaną bez nawiasów.
- Zwykły foreach nie pozwala przypisać do zmiennej iteracyjnej, ale obiekt referencyjny pobrany w pętli może być modyfikowalny.
- Przypisanie tablicy kopiuje referencję. == porównuje tożsamość obiektów tablic, a nie elementy.
- Zakres x[..] i Clone tworzą płytkie kopie: wartości są kopiowane, a dla elementów referencyjnych kopiowane są referencje.
- Przed tab[0] przy szukaniu minimum upewnij się, że tablica jest niepusta.
- Sprawdzaj indeks pochodzący od użytkownika przed dostępem do elementu.