Rozdział 5 - Pętle - Pętla do..while

Pętla do...while jest bardzo podobna do pętli while, z jedną zasadniczą różnicą: pętla do...while zawsze wykona swoje instrukcje, niezależnie od tego, czy jej warunek jest na wstępie spełniony, czy nie. Składnia pętli do...while jest następująca:

do {
  instrukcja1;
  instrukcja2;
  // ...
  instrukcjaN;
} while (warunek);
Zauważmy, że warunek sprawdzający, czy pętla ma działać, jest na końcu pętli, więc pętla do..while zawsze wykona powiązane z nią instrukcje co najmniej raz.

W pierwszym przykładzie w rozdziale o pętli while analizowaliśmy program, który wypisywał na ekran liczby od 1 do 5 – spójrzmy, jak wyglądałby ten sam program korzystający z pętli do..while:

Nazwa pliku: WypiszLiczbyOd1Do5DoWhile.java
public class WypiszLiczbyOd1Do5DoWhile {
  public static void main(String[] args) {
    int x = 1;

    do {
      System.out.println(x++);
    } while (x <= 5);
  }
}

Ta wersja programu niewiele różni się od wersji z pętlą while. Spójrzmy jednak na drugi program – wypisywanie gwiazdek – zmieniony tak, by korzystał z pętli do..while:

Nazwa pliku: WypiszGwiazdkiDoWhile.java
import java.util.Scanner;

public class WypiszGwiazdkiDoWhile {
  public static void main(String[] args) {
    System.out.println("Ile gwiazdek wypisac?");
    int liczbaGwiazdek = getInt();

    do {
      System.out.print("*");
      liczbaGwiazdek--;
    } while (liczbaGwiazdek > 0);
  }

  public static int getInt() {
    return new Scanner(System.in).nextInt();
  }
}

Czy ten program jest równoważny jego wersji z użyciem pętli while?

Spróbujmy uruchomić program i podać 3 jako liczbę gwiazdek do wypisania:

Ile gwiazdek wypisac? 3 ***
Druga próba – tym razem podajemy 0:
Ile gwiazdek wypisac? 0 *

Tym razem program nie zadziałał poprawnie – wypisał jedną gwiazdkę, chociaż poprosiliśmy o 0. Dlaczego tak się stało? Wynika to po prostu ze sposobu działania pętli do..while – ciało pętli tego rodzaju jest zawsze wykonywane co najmniej raz, niezależnie od tego, czy warunek tej pętli jest na początku spełniony, czy nie.

Aby poprawić powyższy program, moglibyśmy opakować pętlę do..while w instrukcję warunkową if, w której sprawdzilibyśmy, czy podana przez użytkownika liczba gwiazdek jest większa od 0:

Nazwa pliku: WypiszGwiazdkiDoWhile.java
import java.util.Scanner;

public class WypiszGwiazdkiDoWhile {
  public static void main(String[] args) {
    System.out.println("Ile gwiazdek wypisac?");
    int liczbaGwiazdek = getInt();

    if (liczbaGwiazdek > 0) {
      do {
        System.out.print("*");
        liczbaGwiazdek--;
      } while (liczbaGwiazdek > 0);
    }
  }

  public static int getInt() {
    return new Scanner(System.in).nextInt();
  }
}

Ta wersja programu działa już poprawnie – dzięki zastosowaniu poznanej w poprzednim rozdziale instrukcji warunkowej if, pętla do..while zostanie wykonana tylko wtedy, gdy liczba gwiazdek podana przez użytkownika będzie większa od 0.

Jak już widać, a co będzie jeszcze lepiej widoczne, gdy poznamy wszystkie cztery rodzaje pętli, różne rodzaje pętli mają różne cechy, a co za tym idzie, różne zastosowania.

Przykład: dodawanie kolejnych liczb

Spójrzmy na jeszcze jeden, ciekawy przykład. Poniższy program to prosty kalkulator sumujący dwie wczytane od użytkownika liczby. Pisaliśmy już podobny program w rozdziale trzecim o zmiennych – to, co sprawia, że ten poniższy jest ciekawszy od tamtego to to, że ten program oferuje dodawanie wielu par liczb dopóki użytkownik nie zażyczy sobie zakończyć działania programu:

Nazwa pliku: DodawanieLiczbDoWhile.java
import java.util.Scanner;

public class DodawanieLiczbDoWhile {
  public static void main(String[] args) {
    int x, y;
    String czyKoniec;

    do {
      System.out.print("Podaj pierwsza liczbe: ");
      x = getInt();

      System.out.print("Podaj druga liczbe: ");
      y = getInt();

      System.out.println("Ich suma wynosi: " + (x + y));

      System.out.print("Czy chcesz zakonczyc program? [t/n] ");
      czyKoniec = getString();

      // wykonuj petle dopoki uzytkownik nie wpisze litery "t"
    } while (!czyKoniec.equals("t"));
  }

  public static int getInt() {
    return new Scanner(System.in).nextInt();
  }

  public static String getString() {
    return new Scanner(System.in).next();
  }
}

W tym programie:

  1. W pętli do..while, pobieramy w każdym obiegu pętli (w każdej iteracji pętli) dwie liczby i wypisujemy ich sumę.
  2. Następnie, prosimy użytkownika o podanie informacji, czy chce zakończyć działanie programu poprzez podanie litery t bądź innej.
  3. Na końcu, sprawdzany jest warunek pętli – jeżeli użytkownik podał inną literę niż t, to warunek !czyKoniec.equals("t") będzie miał wartość true i pętla rozpocznie kolejny obieg, czyli wrócimy do punktu 1. W przeciwnym, razie pętla się zakończy.

Ważne jest tutaj to, że ciało pętli do..while wykonało się jeszcze przed sprawdzeniem, czy pętla powinna się zakończyć, dzięki czemu pobierzemy od użytkownika liczby i wypiszemy ich sumę co najmniej raz.

Przykładowe uruchomienie programu:

Podaj pierwsza liczbe: 10 Podaj druga liczbe: 7 Ich suma wynosi: 17 Czy chcesz zakonczyc program? [t/n] n Podaj pierwsza liczbe: 100 Podaj druga liczbe: -20 Ich suma wynosi: 80 Czy chcesz zakonczyc program? [t/n] t

Prześledźmy powyższe wykonanie programu:

  1. W ciele pętli:
    1. Pobieramy od użytkownika dwie liczby: 10 oraz 7.
    2. Wypisujemy sumę liczb tych: 17.
    3. Pytamy użytkownika, czy chce zakończyć program – aby to zrobić, powinien wpisać literę t z klawiatury.
    4. Pobieramy znak od użytkownika – jest to litera n.
  2. Sprawdzamy warunek działania pętli: !czyKoniec.equals("t"). Wartość zapisana w zmiennej czyKoniec to "n" – taki znak podał użytkownika. Metoda equals zwróci false, a użycie operatora przeczenia logicznego ! (not) spowoduje, że finalna wartość wyrażenia w warunku pętli będzie miała wartość true, czyli pętla powinna działać dalej.
  3. W drugiej iteracji, w ciele pętli:
    1. Pobieramy od użytkownika dwie liczby: 100 oraz -20.
    2. Wypisujemy sumę liczb tych: 80.
    3. Pytamy użytkownika, czy chce zakończyć program.
    4. Pobieramy znak od użytkownika – tym razem jest to litera t.
  4. Ponownie sprawdzamy warunek działania pętli: !czyKoniec.equals("t"). Tym razem, wartość zapisana w zmiennej czyKoniec to "t". Metoda equals zwróci true, a użycie operatora przeczenia logicznego ! (not) spowoduje, że finalna wartość wyrażenia w warunku pętli będzie miała wartość false. Warunek pętli nie jest spełniony – pętla kończy działanie.
Pętle do..while są rzadko wykorzystywane. Zdecydowanie częściej korzysta się z pozostałych trzech rodzajów pętli: while, for, oraz for-each.

Komentarze (2):

  1. Pomocy, od kilku dni się z tym męczę. Nie mogę krzystać z getInt; oraz getString; i pobierać danych od uzytkownika. dodaje na końcu kodu
    public static int getInt() {
    return new Scanner(System.in).nextInt();
    }
    public static String getString() {
    return new Scanner(System.in).next();

    ale pomimo tego wyrzuca mi bład java: illegal start of expression. Help dzięki

    1. Hej, czy możesz wkleić cały kod? Z treści błędu wydaje mi się, że wkleiłeś te metody poza swoją klasę, tzn. prawdopodobnie masz tak wyglądający kod:

      public class MojaKlasa {
        // treść klasy
      }
      
      public static String getInt() {
        // treść metody
      }

      Metoda getInt powinna być wewnątrz klasy MojaKlasa:

      public class MojaKlasa {
        // treść klasy
      
        public static String getInt() {
          // treść metody
        }
      }

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Nie musisz podawać swojego imienia, e-mailu, ani strony www, aby opublikować komentarz. Komentarze muszą zostać zatwierdzone, aby były widoczne na stronie.