Nizovi: mnogo vrijednosti pod jednim imenom
Nizovi u MakeCodeu i Arduino programu: indeksi od nule, petlja kroz niz, dvodimenzionalni nizovi, sizeof, memorija i greška izvan granica niza.
Red kutijica
Varijabla je kutijica s imenom u koju program spremi jedan podatak. Ali što ako program mora pamtiti mnogo sličnih podataka: bodove četiri igrača, pinove četiri LED-ice ili znakove svih 16 tipki tipkovnice? Šesnaest varijabli s gotovo istim imenima teško je pisati i čitati.
Zato postoji niz: red kutijica s jednim zajedničkim imenom. Svaka kutijica ima svoj redni broj, indeks, a indeksi počinju od nule:

U nizu na slici su bodovi četiri igrača. Prvi igrač ima indeks 0, a zadnji indeks 3, iako su igrača četiri. To je kao s katovima zgrade: prizemlje je nulti kat, pa je četvrti kat od dna treći kat.
U jednom nizu sve vrijednosti su iste vrste: sve su brojevi, ili su sve znakovi.
Kako se nizovi koriste na micro:bitu, piše u odjeljku Nizovi u MakeCodeu, a za Arduino radionicu je odjeljak Nizovi u Arduino programu.
Nizovi u MakeCodeu
MakeCode niz zove array. Blokovi za nizove su u kategoriji Arrays, koja se otvori kad klikneš Advanced:
- set list to array of 1 2 3 napravi niz s imenom list i u njega spremi tri broja;
- list get value at 0 pročita prvu vrijednost u nizu;
- length of array list kaže koliko je vrijednosti u nizu.
Nizovi u Arduino programu
Od ovog mjesta stranica je za Arduino radionicu.
Kako napraviti niz
Niz napravimo kao varijablu, ali iza imena u uglatim zagradama napišemo koliko vrijednosti ima, a vrijednosti u vitičastim zagradama:
int bodovi[4] = {12, 7, 15, 9}; // četiri broja tipa int
const int ledice[] = {2, 3, 4, 5}; // broj se smije izostaviti: prevoditelj ih sam prebroji
char znakovi[3] = {'A', 'B', 'C'}; // tri znaka
Do pojedine vrijednosti, elementa niza, dolazimo po indeksu u uglatim zagradama:
Serial.println(bodovi[0]); // prvi element: 12
Serial.println(bodovi[3]); // zadnji element: 9
bodovi[2] = 20; // treći element sada je 20
Nekoliko pravila:
- Ako napišeš manje vrijednosti nego što niz ima elemenata, ostali su 0:
int a[5] = {1, 2};je 1, 2, 0, 0, 0. - Niz napisan iznad
setup()bez vrijednosti pun je nula, kaobilaPritisnuta[4][4]u lekciji Mnogo prekidača na malo pinova. - Broj elemenata zadan je kad niz napraviš. Niz poslije ne može narasti ni se smanjiti.
- Niz ne možeš kopirati znakom
=(a = b;je greška), niti dva niza usporediti s==. Elemente kopiraj ili usporedi jedan po jedan, u petlji.
Petlja kroz niz
Niz je najkorisniji s petljom for: ista naredba izvede se za svaki element, a indeks je brojač petlje. Ovako svi pinovi iz niza ledice postanu izlazi:
const int ledice[] = {2, 3, 4, 5};
const int BROJ_LEDICA = 4;
void setup() {
for (int i = 0; i < BROJ_LEDICA; i++) { // i ide od 0 do 3
pinMode(ledice[i], OUTPUT);
}
}
Uvjet je i < BROJ_LEDICA, a ne i <= BROJ_LEDICA: zadnji indeks je za jedan manji od broja elemenata.
Broj elemenata ne moraš pisati sam. sizeof kaže koliko bajtova nešto zauzima: cijeli niz od četiri int-a zauzima 8 bajtova, a jedan element 2. Kad ih podijeliš, dobiješ broj elemenata, i on ostane točan kad nizu dodaš ili makneš vrijednost:
const int BROJ_LEDICA = sizeof(ledice) / sizeof(ledice[0]); // 8 / 2 = 4
Probaj sam: bodovi igrača
Ovaj program ispiše bodove četiri igrača, njihov zbroj i pobjednika. Učitaj ga i otvori serijski monitor:
const int BROJ_IGRACA = 4;
int bodovi[BROJ_IGRACA] = {12, 7, 15, 9}; // bodovi[0] je prvi igrač, bodovi[3] zadnji
void setup() {
Serial.begin(9600);
int zbroj = 0;
int najbolji = 0; // indeks igrača s najviše bodova
for (int i = 0; i < BROJ_IGRACA; i++) { // i ide od 0 do 3
Serial.print("Igrač ");
Serial.print(i + 1); // ljudi broje od 1
Serial.print(": ");
Serial.println(bodovi[i]);
zbroj = zbroj + bodovi[i];
if (bodovi[i] > bodovi[najbolji]) {
najbolji = i;
}
}
Serial.print("Ukupno: ");
Serial.println(zbroj);
Serial.print("Pobjednik: igrač ");
Serial.println(najbolji + 1);
}
void loop() {
}
U serijskom monitoru piše:
Igrač 1: 12
Igrač 2: 7
Igrač 3: 15
Igrač 4: 9
Ukupno: 43
Pobjednik: igrač 3
Program pamti indeks najboljeg igrača, a ne njegove bodove: iz indeksa zna i bodove (bodovi[najbolji]) i koji je to igrač. Ljudi broje od 1, pa programu dodamo 1 tek kad ispisuje.
Dodaj petog igrača: promijeni BROJ_IGRACA u 5 i dodaj njegove bodove u vitičaste zagrade. Ostatak programa ostaje isti, i to je cijela prednost niza.
Dvodimenzionalni niz
Niz može imati i retke i stupce, kao tablica. Tada ima dva indeksa: prvi je redak, a drugi stupac. Tako su u lekciji Mnogo prekidača na malo pinova spremljeni znakovi tipkovnice 4 × 4:
const char znakovi[4][4] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

znakovi[1][2] je znak u retku 1 i stupcu 2, dakle '6'. Kroz dvodimenzionalni niz idemo petljom u petlji: vanjska ide kroz retke, a unutarnja kroz stupce.Izvan granica niza
U nizu od četiri elementa postoje samo indeksi od 0 do 3. Što se dogodi s bodovi[4]?
![Memorija kao red kućica: siva kućica, četiri plave kućice niza s brojevima 12, 7, 15 i 9 i indeksima 0 do 3, narančasta kućica druge varijable i opet siva. Crvena strelica s natpisom [4] = 0 pokazuje na narančastu kućicu, u kojoj je prekrižen broj 3 i upisana crvena 0, a pokraj je crveni križić](/images/nizovi-izvan.png)
C++ ne provjerava je li indeks u granicama niza. Elementi niza su u memoriji jedan do drugoga, a iza zadnjeg je obično neka druga varijabla. bodovi[4] zato pročita ono što je u memoriji iza niza, a bodovi[4] = 0 u tu drugu varijablu upiše 0.
Nema poruke o grešci
Prevoditelj ne javi grešku, a program se ne zaustavi. Samo se neka druga varijabla tiho promijeni, pa program počne raditi čudno, a uzrok je na sasvim drugom mjestu. Najčešći uzrok je uvjet petlje i <= 4 umjesto i < 4.
Kad program radi čudno, a koristi nizove, prvo provjeri uvjete petlji i indekse.
Niz i funkcija
Niz možemo predati funkciji, ali funkcija ne zna koliko elemenata niz ima. Zato joj broj elemenata predamo kao drugi parametar:
int zbroji(const int brojevi[], int koliko) {
int zbroj = 0;
for (int i = 0; i < koliko; i++) {
zbroj = zbroj + brojevi[i];
}
return zbroj;
}
Poziv je zbroji(bodovi, BROJ_IGRACA). const kaže da funkcija niz samo čita. Bez const funkcija bi smjela mijenjati elemente, i to bi bili elementi pravog niza, a ne njihova kopija.
Nizovi i memorija
Arduino Uno ima samo 2 KB (2048 bajtova) memorije za varijable, a nizovi je brzo napune: niz od 1000 int-ova zauzme 2000 bajtova, i za sve ostalo ostane samo 48. Zato:
- Odaberi najmanji tip koji je dovoljan. Za brojeve od 0 do 255 dovoljan je
byte, koji zauzima upola manje odint-a. - Pazi na veliku tablicu koja se ne mijenja. Na Unu je i takva tablica u memoriji za varijable, osim ako je spremiš u memoriju za program s
PROGMEM(pogledaj savjete na stranici Arduino IDE). - Pri prevođenju Arduino IDE ispiše koliko memorije zauzimaju globalne varijable: Global variables use … bytes.
Tekst je niz znakova
I tekst je niz: char ime[] = "Ana"; je niz znakova 'A', 'n' i 'a'. Ali taj niz ima četiri elementa, a ne tri. Na kraju je još jedan znak, '\0', broj 0, koji označava gdje tekst završava. Tako Serial.println(ime) zna kada treba stati.
Nizove smo koristili u lekciji Mnogo prekidača na malo pinova, za pinove redaka i stupaca, znakove tipki i stanje svake tipke. U lekciji Igra reakcije jedan od izazova sprema frekvencije fanfare u niz.
Što smo naučili?
- Niz je red varijabli s jednim imenom. Svaka ima svoj indeks, a indeksi počinju od 0, pa je zadnji indeks za jedan manji od broja elemenata.
- U MakeCodeu nizovi su u kategoriji Arrays, pod Advanced. U Arduino programu niz pišemo s uglatim zagradama:
int bodovi[4] = {12, 7, 15, 9};. - S petljom
forista naredba izvede se za svaki element niza.sizeof(niz) / sizeof(niz[0])daje broj elemenata. - Dvodimenzionalni niz ima retke i stupce:
znakovi[1][2]je redak 1, stupac 2. - C++ ne provjerava granice niza. Indeks izvan niza tiho promijeni neku drugu varijablu.
- Nizovi brzo napune 2 KB memorije Una, pa za njih biramo najmanji dovoljan tip.
Mali kviz
1. Niz ima šest elemenata. Koji je indeks prvog, a koji zadnjeg?
2. Koliko je bodovi[1] u nizu int bodovi[4] = {12, 7, 15, 9};?
3. Što ne valja u petlji for (int i = 0; i <= 4; i++) za niz od četiri elementa?
i = 4, a takvog elementa nema. Program tada pročita ili promijeni memoriju iza niza. Ispravan uvjet je i < 4.4. Što je u nizu int a[4] = {5};?
5. Koliko bajtova zauzima niz byte slika[8], a koliko niz long vremena[8] na Unu?
byte ima jedan bajt, pa prvi niz zauzima 8 bajtova. long ima četiri, pa drugi zauzima 32 bajta.6. Koji je znak znakovi[3][0] u tablici tipkovnice?
'*'. Redak 3 je zadnji redak ('*', '0', '#', 'D'), a stupac 0 prvi znak u njemu.7. Zašto funkciji osim niza predajemo i broj njegovih elemenata?
8. Koliko elemenata ima niz char ime[] = "Ana";?
'\0' na kraju, koji označava kraj teksta.