← Strona główna

05 — Pętle while

Warunki kontynuacji, break, continue, pętle nieskończone, walidacja wejścia.

Struktury i pętle

1. Jak działa pętla while?

Pętla while wykonuje blok kodu tak długo, jak warunek jest prawdziwy. W przeciwieństwie do for — nie iteruje po sekwencji, tylko sprawdza warunek przed każdym obrotem.

  • Warunek sprawdzany jest przed każdym obrotem — jeśli na starcie jest fałszywy, pętla w ogóle się nie wykona
  • Musisz sam zadbać o zmianę warunku — inaczej pętla nigdy się nie skończy
  • Idealna gdy nie wiesz z góry ile razy pętla ma się wykonać
  • Używana do walidacji wejścia, menu, gier, odczytywania danych
Schemat while warunek:
    # ciało pętli
    # zmień coś co wpływa na warunek!
Przykład — podstawy while
# Odliczanie
licznik = 5
while licznik > 0:
    print(licznik, end=" ")
    licznik -= 1       # zmiana warunku!
print("Start!")
# 5 4 3 2 1 Start!

# Suma cyfr liczby
n = 12345
suma = 0
while n > 0:
    suma += n % 10     # ostatnia cyfra
    n //= 10           # usuń ostatnią cyfrę
print(suma)            # 15

# Pętla while jako for
i = 0
while i < 5:
    print(i, end=" ")
    i += 1
# 0 1 2 3 4

2. break, continue i else w while

break — natychmiast kończy pętlę while, niezależnie od warunku.

continue — pomija resztę bieżącego obrotu i wraca do sprawdzenia warunku.

else — wykonuje się gdy warunek while stał się fałszywy (pętla skończyła się naturalnie, bez break).

  • break — wyjdź z pętli natychmiast
  • continue — idź do następnego obrotu
  • else — po normalnym zakończeniu pętli
  • Pamiętaj: continue musi mieć zmianę warunku przed sobą lub pętla będzie się kręcić w kółko
Pułapka z continue Jeśli continue pojawia się przed zmianą licznika — licznik nigdy się nie zmieni i powstanie nieskończona pętla! Zmianę licznika umieszczaj przed continue.
Przykład — break, continue, else
# break — zatrzymaj po znalezieniu
liczby = [3, 7, 2, 8, 5, 1]
i = 0
while i < len(liczby):
    if liczby[i] == 8:
        print(f"Znalazłam 8 na pozycji {i}!")
        break
    i += 1
else:
    print("Nie znalazłam 8.")

# continue — pomiń zera
i = 0
dane = [4, 0, 2, 0, 7, 0, 3]
suma = 0
while i < len(dane):
    if dane[i] == 0:
        i += 1
        continue    # pomiń, ale NAJPIERW zwiększ i!
    suma += dane[i]
    i += 1
print(f"Suma (bez zer): {suma}")   # 16

# while...else
n = 10
while n > 0:
    n -= 3
else:
    print(f"Pętla skończyła się, n = {n}")  # n = -2

3. Pętle nieskończone — while True

while True to celowa pętla nieskończona — wykonuje się bez końca, aż do break. To standard dla menu, gier i walidacji wejścia.

  • Zawsze musi być break — inaczej program się zawiesi
  • Czytelniejsza niż skomplikowany warunek w while
  • Typowy wzorzec: "zrób coś, sprawdź warunek wyjścia, powtórz"
  • W grach: pętla główna gry to zazwyczaj while True
Wzorzec — menu Wyświetl opcje → wczytaj wybór → obsłuż wybór → jeśli "wyjście" to break, inaczej wróć na górę.
Przykład — while True i menu
# Proste menu
while True:
    print("\n=== MENU ===")
    print("1. Powitanie")
    print("2. Data")
    print("0. Wyjście")

    wybor = input("Wybierz: ")

    if wybor == "1":
        print("Cześć!")
    elif wybor == "2":
        import datetime
        print(datetime.date.today())
    elif wybor == "0":
        print("Do widzenia!")
        break
    else:
        print("Nieznana opcja.")

# Zgadywanie liczby
import random
sekret = random.randint(1, 100)
proby  = 0

while True:
    proba = int(input("Zgadnij (1-100): "))
    proby += 1
    if proba < sekret:
        print("Za mało!")
    elif proba > sekret:
        print("Za dużo!")
    else:
        print(f"Brawo! {proby} prób.")
        break

4. Walidacja danych wejściowych

Jednym z najczęstszych zastosowań while na egzaminie jest wymuszenie poprawnego wejścia od użytkownika — pętla pyta ponownie gdy dane są złe.

  • Wzorzec: wczytaj → sprawdź → jeśli złe: komunikat i wróć; jeśli dobre: break
  • str.isdigit() — sprawdza czy tekst to same cyfry
  • str.isnumeric() — podobne, ale obsługuje też unicode
  • Do pełnej walidacji liczb zmiennoprzecinkowych lepiej użyć try/except
Na egzaminie Jeśli zadanie mówi "wczytuj dopóki użytkownik nie poda poprawnej wartości" — to właśnie while True z walidacją wewnątrz.
Przykład — walidacja wejścia
# Walidacja liczby całkowitej w zakresie
while True:
    tekst = input("Podaj ocenę (1-6): ")
    if tekst.isdigit():
        ocena = int(tekst)
        if 1 <= ocena <= 6:
            break
        else:
            print("Ocena musi być od 1 do 6.")
    else:
        print("To nie jest liczba!")

print(f"Wpisałaś ocenę: {ocena}")

# Walidacja tak/nie
while True:
    odp = input("Kontynuować? (t/n): ").lower().strip()
    if odp in ("t", "n"):
        break
    print("Wpisz 't' lub 'n'.")

if odp == "t":
    print("Kontynuujemy!")
else:
    print("Kończymy.")

5. Kiedy while, a kiedy for?

SytuacjaUżyj
Znasz z góry liczbę powtórzeńfor
Iterujesz po liście, tekście, krotcefor
Używasz range()for
Nie wiesz kiedy się skończywhile
Walidacja wejścia od użytkownikawhile
Menu / pętla główna programuwhile True
Czekasz na spełnienie warunkuwhile
Algorytm (Euklides, dzielenie cyfr)while
Zasada praktyczna Każdą pętlę while da się przepisać na for i odwrotnie — ale czytelność kodu znacząco spada. Wybieraj tę która lepiej opisuje intencję.
Przykład — for i while do tego samego zadania
# Suma liczb od 1 do 10 — oba sposoby

# for — czytelniej gdy znamy zakres
suma = 0
for i in range(1, 11):
    suma += i
print(suma)   # 55

# while — działa, ale mniej naturalne
suma = 0
i    = 1
while i <= 10:
    suma += i
    i += 1
print(suma)   # 55

# Wczytywanie aż do słowa "koniec" — while naturalne
slowa = []
while True:
    slowo = input("Słowo (lub 'koniec'): ")
    if slowo.lower() == "koniec":
        break
    slowa.append(slowo)
print(f"Wpisałaś: {slowa}")

6. Algorytmy z pętlą while

Wiele klasycznych algorytmów naturalnie korzysta z while — warunek zależy od bieżących danych, nie od z góry ustalonej liczby kroków.

  • NWD Euklidesa — dziel aż reszta = 0
  • Odwrócenie liczby — pobieraj cyfry aż liczba = 0
  • Potęgowanie — mnóż aż wykładnik = 0
  • Wyszukiwanie binarne — zawężaj zakres aż lewy > prawy
NWD na egzaminie Algorytm Euklidesa: nwd(a, b) — dopóki b ≠ 0, zamień a na b, a b na a % b. Gdy b = 0, wynikiem jest a. Musisz go znać zarówno w wersji iteracyjnej jak i rekurencyjnej.
Przykład — algorytmy z while
# NWD — algorytm Euklidesa (iteracyjny)
a = int(input("Pierwsza liczba: "))
b = int(input("Druga liczba: "))

while b != 0:
    a, b = b, a % b

print(f"NWD = {a}")

# Odwrócenie liczby
n        = int(input("Podaj liczbę: "))
odwrocona = 0
oryginalna = n

while n > 0:
    cyfra     = n % 10
    odwrocona = odwrocona * 10 + cyfra
    n        //= 10

print(f"Odwrócona: {odwrocona}")

# Sprawdzenie palindromu liczbowego
if oryginalna == odwrocona:
    print("To palindrom!")
else:
    print("To nie palindrom.")

Zadania przykładowe z omówieniem

Zadanie 1 Walidacja wieku z komunikatem łatwe

Napisz program który wczytuje wiek użytkownika. Jeśli wiek jest poza zakresem 0–120 lub nie jest liczbą całkowitą — wypisz komunikat i pytaj ponownie. Po wczytaniu poprawnego wieku wypisz czy osoba jest małoletnia czy pełnoletnia.

Rozwiązanie
while True:
    tekst = input("Podaj wiek (0-120): ").strip()

    if not tekst.isdigit():
        print("Błąd: podaj liczbę całkowitą.")
        continue

    wiek = int(tekst)

    if 0 <= wiek <= 120:
        break
    else:
        print("Błąd: wiek musi być w zakresie 0-120.")

if wiek >= 18:
    print(f"Masz {wiek} lat — jesteś pełnoletnia/y.")
else:
    print(f"Masz {wiek} lat — jesteś małoletnia/y.")
    print(f"Do pełnoletności: {18 - wiek} lat.")
Omówienie krok po kroku
  1. while True — pętla walidacji
    Nie wiemy ile razy użytkownik wpisze złe dane. while True to naturalny wybór — pętla trwa aż do poprawnego wejścia i break.
  2. isdigit() przed int()
    Najpierw sprawdzamy czy tekst to cyfry — dopiero potem bezpiecznie robimy int(). Gdybyśmy zrobili int() bez sprawdzenia i użytkownik wpisał "abc" — program by się wywalił.
  3. continue po błędzie
    Po wypisaniu komunikatu o błędzie continue wraca na górę pętli — od razu do input(). Nie wykonuje się reszta kodu w tym obrocie.
  4. break po sukcesie
    Gdy wiek jest poprawny — break wyrywa z pętli. Kod po pętli wykonuje się z poprawną wartością wiek.
Zadanie 2 Kalkulator sumy — wczytuj aż do 0 łatwe

Wczytuj liczby od użytkownika i dodawaj je do sumy. Zakończ gdy użytkownik wpisze 0. Wypisz sumę, liczbę wczytanych wartości (bez zera) i średnią.

Rozwiązanie
suma    = 0
licznik = 0

while True:
    n = float(input("Podaj liczbę (0 = koniec): "))

    if n == 0:
        break

    suma    += n
    licznik += 1

if licznik > 0:
    print(f"Suma:    {suma:.2f}")
    print(f"Ilość:   {licznik}")
    print(f"Średnia: {suma / licznik:.2f}")
else:
    print("Nie podałaś żadnej liczby.")
Omówienie krok po kroku
  1. Zmienne przed pętlą
    suma = 0 i licznik = 0 inicjalizujemy przed pętlą — będą aktualizowane w każdym obrocie.
  2. Warunek wyjścia wewnątrz pętli
    Wczytujemy najpierw, potem sprawdzamy. Jeśli to 0 — break. Zero nie trafia do sumy ani licznika.
  3. Zabezpieczenie przed dzieleniem przez 0
    if licznik > 0 przed obliczeniem średniej — gdy użytkownik od razu wpisze 0, nie ma co dzielić. Brak tej kontroli = ZeroDivisionError.
Zadanie 3 Gra: wyżej — niżej średnie

Program losuje liczbę od 1 do 100. Użytkownik zgaduje — program mówi "za mało", "za dużo" lub "brawo". Po odgadnięciu wypisz ile prób zajęło. Ogranicz do 10 prób — jeśli nie odgadnie, wypisz komunikat i ujawnij liczbę.

Rozwiązanie
import random

sekret   = random.randint(1, 100)
proby    = 0
max_prob = 10
odgadnieto = False

while proby < max_prob:
    proby += 1
    pozostalo = max_prob - proby

    proba = int(input(f"Próba {proby}/{max_prob} — zgadnij: "))

    if proba < sekret:
        print(f"Za mało! (pozostało {pozostalo} prób)")
    elif proba > sekret:
        print(f"Za dużo! (pozostało {pozostalo} prób)")
    else:
        print(f"Brawo! Zgadłaś w {proby} próbach!")
        odgadnieto = True
        break

if not odgadnieto:
    print(f"Nie udało się. Liczba to: {sekret}")
Omówienie krok po kroku
  1. while proby < max_prob
    Zamiast while True używamy warunku na liczbę prób. Pętla sama się skończy po 10 próbach — nie potrzebujemy dodatkowego break dla limitu.
  2. Flaga odgadnieto
    Zmienna boolowska ustawiana na True gdy sukces. Po pętli sprawdzamy ją — jeśli wciąż False, znaczy że pętla skończyła się przez limit, nie przez odgadnięcie.
  3. Licznik prób na początku obrotu
    proby += 1 przed input() — dzięki temu możemy od razu wypisać "Próba 1/10" zanim użytkownik cokolwiek wpisze.
  4. import random i randint()
    random.randint(1, 100) losuje liczbę całkowitą z zakresu 1–100 włącznie (obie granice!). To różnica od range() gdzie stop jest wykluczony.

Zadania do samodzielnego rozwiązania

Wszystkie zadania rozwiąż używając pętli while. Zwróć uwagę na warunki wyjścia i walidację wejścia.

1★☆☆

Silnia iteracyjna

Wczytaj liczbę całkowitą n ≥ 0. Oblicz n! używając pętli while (bez rekurencji). Wypisz kolejne kroki obliczeń.

Wskazówka: wynik = 1, mnóż przez kolejne liczby aż do n
2★☆☆

Zbieranie ocen

Wczytuj oceny (1–6) aż użytkownik wpisze -1. Wypisz wszystkie oceny, średnią i ile ich było. Ignoruj niepoprawne wartości.

Wskazówka: while True, walidacja zakresu, break na -1
3★★☆

NWW dwóch liczb

Oblicz Najmniejszą Wspólną Wielokrotność (NWW) dwóch liczb. Wzór: NWW(a,b) = a*b / NWD(a,b). Najpierw oblicz NWD pętlą while.

Wskazówka: algorytm Euklidesa, potem a * b // nwd
4★★☆

Kalkulator z historią

Napisz kalkulator w pętli while z menu: dodawanie, odejmowanie, mnożenie, dzielenie, wyświetl historię obliczeń, wyjście. Każdy wynik zapisuj do listy.

Wskazówka: while True, lista historia = [], append()
5★★☆

Cyfry liczby

Wczytaj liczbę całkowitą dodatnią. Używając while wypisz jej cyfry od końca do początku, policz je i oblicz ich sumę.

Wskazówka: n % 10 daje ostatnią cyfrę, n //= 10 usuwa ją
6★★★

Wyszukiwanie binarne

Masz posortowaną listę liczb. Zaimplementuj wyszukiwanie binarne pętlą while — zawężaj zakres [lewy, prawy] sprawdzając środkowy element. Wypisz ile kroków zajęło.

Wskazówka: srodek = (lewy + prawy) // 2, porównaj z szukaną