Zakresy (ranges)

Zakres to wygodny sposób na opisanie ciągu wartości „od – do”. Poznasz zapis 1..10, warianty until, downTo i step, a przede wszystkim operatory in / !in do sprawdzania, czy wartość należy do zakresu.

1..10 in / !in until · downTo step
1

Czym jest zakres

Zakres opisuje ciąg kolejnych wartości od początku do końca. Tworzymy go operatorem ... Zapis 1..10 oznacza „wszystkie liczby od 1 do 10, włącznie z 10”.

Tworzenie zakresu
val zakres = 1..10      // liczby od 1 do 10 (z 10)
println(zakres)            // 1..10
println(zakres.first)      // 1  – pierwsza wartość
println(zakres.last)       // 10 – ostatnia wartość

Zakres to pełnoprawna wartość – można go zapisać w zmiennej i używać wielokrotnie, np. do sprawdzania przynależności, o czym za chwilę.

2

in / !in – sprawdzanie przynależności

Najczęstsze zastosowanie zakresu to pytanie: „czy ta wartość mieści się w przedziale?”. Operator in daje true, gdy wartość należy do zakresu; !in – odwrotnie.

Czy wartość należy do zakresu
val wiek = 16

println(wiek in 1..18)    // true  – 16 mieści się w 1..18
println(wiek !in 1..18)   // false
println(25 in 1..18)      // false – 25 jest poza zakresem

Świetnie łączy się to z instrukcją if – do prostej walidacji danych:

Walidacja z użyciem in
val ocena = 4

if (ocena in 1..6) {
    println("Poprawna ocena")
} else {
    println("Ocena spoza skali!")
}
in działa też w when

Operator in spotkałeś już w gałęziach when (in 50..74 -> ...). To dokładnie ten sam mechanizm sprawdzania przynależności do zakresu.

3

until – bez ostatniej wartości

Czasem chcemy zakres, który nie obejmuje ostatniej liczby. Służy do tego until: zapis 1 until 10 to liczby od 1 do 9 (czyli 10 jest pominięte).

Zakres otwarty z prawej strony
println(9 in 1 until 10)    // true  – 9 należy (1..9)
println(10 in 1 until 10)   // false – 10 już NIE należy
Nowszy zapis: ..<

To samo co 1 until 10 można zapisać operatorem 1..<10. Oba znaczą „od 1 do 10 bez 10”. until jest bardziej opisowe i czytelne dla początkujących – możesz spokojnie przy nim zostać.

4

downTo – zakres malejący

Operator .. zawsze idzie „w górę”. Żeby uzyskać zakres malejący (od większej do mniejszej wartości), używamy downTo.

Zakres w dół
val odliczanie = 10 downTo 1   // 10, 9, 8, ... 1
println(5 in odliczanie)            // true
10..1 jest PUSTE

Zapis 10..1 nie tworzy zakresu malejącego – tworzy zakres pusty (bo .. idzie tylko w górę). Aby liczyć w dół, zawsze użyj downTo.

5

step – co ile

Domyślnie zakres idzie co 1. Słowo step ustala krok – co ile wartości „przeskakujemy”. Działa zarówno z zakresem rosnącym, jak i z downTo.

Co drugą i co trzecią wartość
val parzyste = 0..10 step 2      // 0, 2, 4, 6, 8, 10
val wSpadku  = 9 downTo 0 step 3 // 9, 6, 3, 0

Pełnię swoich możliwości step i downTo pokazują dopiero w połączeniu z pętlą for – zobaczysz to za moment.

6

Zakresy znaków

Zakresy działają nie tylko na liczbach, ale i na znakach (typ Char). Pozwala to wygodnie sprawdzić, czy znak jest np. małą literą albo cyfrą.

Czy znak jest literą / cyfrą
val znak = 'k'

println(znak in 'a'..'z')   // true  – mała litera
println(znak in 'A'..'Z')   // false – nie jest wielką literą
println('7' in '0'..'9')    // true  – cyfra
7

Zakresy w pętli for

Najczęściej zakresów używa się do powtarzania – żeby przejść po kolejnych wartościach. Pętlę for omówimy dokładnie w następnej lekcji, ale zobacz już teraz, jak ładnie współgra z zakresami:

Przejście po zakresie
for (i in 1..5) {
    print("$i ")        // 1 2 3 4 5
}
println()

for (i in 10 downTo 1 step 2) {
    print("$i ")        // 10 8 6 4 2
}
Tu tylko zapowiedź

Składnię pętli for i jej zastosowania omówimy dokładnie w następnej lekcji. Na teraz zapamiętaj, że to właśnie zakresy „napędzają” najczęstsze pętle w Kotlinie.

8

Częste błędy

❌ Błąd 1: a..b dla wartości malejących

❌ Pusty zakres

println(5 in 10..1)
// false – 10..1 jest PUSTE,
// nic do niego nie należy

✅ downTo dla malejących

println(5 in 10 downTo 1)
// true

❌ Błąd 2: pomylenie .. z until (off-by-one)

❌ until pomija ostatnią

// chcemy uwzględnić 10
println(10 in 1 until 10)
// false – until pomija 10

✅ .. obejmuje ostatnią

println(10 in 1..10)
// true

❌ Błąd 3: brak in przy sprawdzaniu

❌ Porównanie do zakresu

val x = 5
if (x == 1..10) {
    // Błąd! liczby nie da się
    // porównać do zakresu przez ==
}

✅ Przynależność przez in

val x = 5
if (x in 1..10) {
    println("w zakresie")
}

❌ Błąd 4: step zero lub ujemny

❌ Krok musi być dodatni

val z = 1..10 step 0
// Błąd! krok musi być
// większy od zera

✅ Kierunek przez downTo, krok > 0

val z = 10 downTo 1 step 2
// w dół z krokiem 2
9

Podsumowanie

  • 1..10 tworzy zakres od 1 do 10 włącznie (operator ..).
  • in / !in sprawdzają, czy wartość należy do zakresu (zwracają Boolean).
  • until tworzy zakres bez ostatniej wartości (1 until 10 = 1..9); nowszy zapis to 1..<10.
  • downTo daje zakres malejący; samo 10..1 jest puste.
  • step ustala krok (co ile wartości), zawsze dodatni.
  • Zakresy działają też na znakach: 'a'..'z', '0'..'9'.
  • Zakresy najczęściej napędzają pętlę for (następna lekcja).
10

Zadania do wykonania

Zadania z wczytywaniem uruchamiaj w IntelliJ IDEA; pozostałe w Kotlin Playground.

Zadanie 1 łatwe

Wczytaj liczbę i sprawdź operatorem in, czy mieści się w zakresie 1..100. Wypisz wynik typu Boolean.

Zadanie 2 łatwe

Wczytaj ocenę i za pomocą !in sprawdź, czy jest spoza skali 1..6. Jeśli tak – wypisz ostrzeżenie.

Zadanie 3 łatwe

Wczytaj pojedynczy znak (np. pierwszy znak wczytanego tekstu: readln()[0]) i sprawdź, czy jest małą literą ('a'..'z') lub cyfrą ('0'..'9').

Zadanie 4 średnie

Napisz prosty walidator wieku: wczytaj liczbę i sprawdź, czy mieści się w sensownym zakresie 0..120. Połącz in z if: dla wartości w zakresie wypisz „Wiek poprawny”, w przeciwnym razie „Błędny wiek”. Dodatkowo wypisz, czy osoba jest pełnoletnia (zakres 18..120).