Twitter: @grzegg
Kategoria: java, Tagi: - - .

Java [10] – Instrukcje wyboru cz. II

Poprzednio poznaliśmy podstawową instrukcję warunkową, czyli if…else. Jest ona na tyle uniwersalna, że w zasadzie można używać tylko jej w sytuacjach, w których należy wykorzystać instrukcję warunkową. Ale Java udostępnia także inne możliwości, które warto wykorzystywać choćby ze względu na przejrzystość kodu. Przy okazji wyjaśnię jak porównać jak porównać dwa łańcuchy znaków.

Ta strona jest częścią materiałów do kursu “Programowanie w Javie z elementami bioinformatyki dla poczatkujących”. Pozostałe materiały znajdziesz tutaj

Jeżeli…, a jeżeli nie ale… (if..else if..else)

Program z poprzedniej lekcji działa, ale jeśli będziemy mieli do czynienia z coraz bardziej zagnieżdżającymi się blokami kodu, jego przejrzystość mimo zastosowania wcięć będzie maleć. Jeśli mamy do czynienia z taką sytuacją, że należy sprawdzić kolejno wiele warunków i w przypadku natrafienia rezultat true jednego z nich nie sprawdzamy już następnych, warto użyć rozszerzonej wersji if..else czyli if..else if..else.

if (warunek1) {
// Kod wykonywany jeśli warunek1 zwraca wartość true
}
else if (warunek2) {
// Kod wykonywany jeśli warunek2 zwraca wartość true
}
else {
// Kod wykonywany jeśli żaden z powyższych warunków
// nie zwróci wartości true
}

Jak widać między wyrażeniami if oraz else pojawiło się wyrażenie if else, po którym także należy umieścić warunek. Jego prawdziwość jest sprawdzana wtedy, gdy poprzedni warunek nie zwraca wartości true. Jeśli żadne z wyrażeń if oraz if else nie zwróci wartości true to wykonywane są polecenia znajdujące się w bloku kodu po wyrażeniu else. Wyrażenie else oczywiście można pominąć. Co ważne, w zasadzie nie ma ograniczeń co do liczby wyrażeń else if co pozwala sprawdzać wiele warunków po kolei.

Wykorzystując taką konstrukcję można zmodyfikować program na przykład tak:

Ćwiczenie:

Spróbuj zmodyfikować kod w ten sposób, żeby program sprawdzał także podzielność przez 5, 7 i 11.

A oto inny przykład, poprawione zadanie z poprzedniej lekcji. Prawda, że kod jest bardziej czytelny?

Włącz to (switch)

Ostatnią z omawianych instrukcji wyboru jest switch, pozwalająca na łatwe uruchamianie fragmentów kodu w zależności od wartości wyrażenia. Ogólny schemat stosowania instrukcji można przedstawić tak:

switch (wyrażenie) {
   case wartość1:
      //kod który się wykonuje, jeżeli wyrażenie zwraca wartość wartość1
      break;
   case wartość2:
      //kod który się wykonuje, jeżeli wyrażenie zwraca wartość wartość2
      break;
   …
   default:
      //kod który się wykonuje domyślnie, jeśli żadne z powyższych nie pasuje
}

Warto zwrócić uwagę, że:

  • Struktura switch jest nieco nietypowa dla Javy. Bloki kodu wykonujące po poszczególnych wyrażeniach case są poprzedzone dwukropkiem i nie są objęte parą nawiasów klamrowych. Parą nawiasów klamrowych jest natomiast objęty cały blok kodu objęty wyrażeniem switch
  • Na końcu każdego z nich znajduje się komenda break. Powoduje ona przeskok wykonywanego programu na koniec kodu objętego switch. Co się dzieje, jeśli break nie ma wyjaśnię później.
  • Kod umieszczany po wyrażeniu default wykonuje się, gdy żadne z wyrażeń znajdujące się po poprzedzających wyrażeniach case nie jest prawdziwe.
  • Znajdujące się przy switch wyrażenie powinno zwracać wartość typu byte, char, short, int, lub łańcuch znaków (String). Może to być nazwa zmiennej zwracającej wartość jednego z wymienionych typów.

Poniższy kod pokazuje działanie instrukcji switch na przykładzie prostego programu tłumaczącego oceny wyrażone w liczbach na oceny słowne (w skali akademickiej):

Przykład jest chyba na tyle czytelny, że nie wymaga komentarza.

Spróbujmy teraz sprawdzić co się stanie jeśli usuniemy instrukcję break na przykład przy case 3. Teraz po uruchomieniu wpisz ocenę 3:


Podaj ocenę w formie liczby całkowitej
3
Dostateczny
Dobry

Wynik jest nieco zaskakujący. Zauważ, że wykonała się nie tylko instrukcja znajdująca się przy case 3 ale także ta, która powinna się wykonać dla wartości oceny równej 4. Wynika z tego, że usunięcie break powoduje przejście wykonywania kodu do bloku przyporządkowanemu kolejnej instrukcji case niezależnie od tego czy sprawdzana wartość wyrażenia pasuje czy nie. Jeśli usuniemy wszystkie instrukcje break, wykonają się wszystkie bloki kodu objęte instrukcją switch, łącznie z tym który znajduje się po default.

W nowszych wersjach Javy w instrukcji switch można również używać łańcuchów znaków (String). Odwróćmy zatem sposób działania ostatniego programu, teraz ocena wpisana w formie słownej, będzie tłumaczona na cyfrę:

Przykładowa sesja może wyglądać tak:


Podaj ocenę w formie słownej (ndst/dst/db/bdb)
dst
3

Porównania łańcuchów znaków

Ostatni przykład pokazał, że można wykorzystywać także łańcuchy znaków w instrukcji warunkowej typu switch, która porównuje określony String z innymi łańcuchami umieszczonymi przy instrukcjach case i na tej podstawie była dokonywana decyzja dotycząca uruchomienia lub nie poszczególnych bloków kodu.

W instrukcjach typu if..else mieliśmy natomiast do czynienia z warunkami, które zwracały true lub false. Dotychczas w takich testach stosowaliśmy liczby sprawdzając na przykład, czy są sobie równe, czy jedna jest większa od drugiej itp. Jak jednak sprawdzić czy jeden ciąg znaków odpowiada innemu? Zapewne przychodzi Ci do głowy coś w tym stylu:

Po uruchomieniu uzyskujemy Ten sam rodzaj, może się wydawać, że ten sposób działa. Ale spróbujmy nieco zmodyfikować kod:

Teraz nasza interakcja z programem może wyglądać następująco:


Podaj pierwszy rodzaj
Poa
Podaj drugi rodzaj
Poa
Różne rodzaje

Jak widać to nie takie proste. Porównywanie łańcuchów znaków za pomocą operatora ==, nie wchodząc w szczegóły, udaje się tylko czasami nie należy więc go stosować. Jak zatem porównać dwa łańcuchy znaków?
Wcześniej wspomniałem, że String należy do typów obiektowych a także, że obiekt może przechowywać dane i wykonywać pewne operacje.

Zmodyfikuj program w ten sposób:



if (rodzaj1.equals(rodzaj2))


Teraz działanie jest poprawne:


Podaj pierwszy rodzaj
Poa
Podaj drugi rodzaj
Poa
Ten sam rodzaj

Jak to działa? Obiekty typu String nie tylko przechowują łańcuchy znaków ale mogą wykonywać wiele użytecznych operacji na nich, miedzy innymi porównywać do innych łańcuchów znaków. Możliwości z tym związane omówię szerzej w osobnej lekcji, teraz skupimy się właśnie na prostym porównywaniu łańcuchów.
Jedną z dostępnych metod służących porównywaniu znaków jest właśnie użyta przez nas metoda equals(). Zauważ, że nazwę obiektu i metodę, którą na nim wywołujemy łączy kropka. Metoda equals() przyjmuje jako argument inny String. Jeśli oba łańcuchy znaków są takie same, to zwracana jest wartość true, jeśli nie to otrzymujemy false. Metoda equals() ma jednak tą właściwość, że zwraca uwagę na wielkość znaków, zatem „Poa” i „poa” to dla niej różne łańcuchy.


Podaj pierwszy rodzaj
Poa
Podaj drugi rodzaj
poa
Różne rodzaje

Jeśli wielkość liter nie jest dla nas istotna to należy użyć innej metody: rodzaj1.equalsIgnoreCase(). Jeśli więc zmienimy stosowane porównanie na takie:


if (rodzaj1.equalsIgnoreCase(rodzaj2))

To wynik może być następujący:


Podaj pierwszy rodzaj
Poa
Podaj drugi rodzaj
poa
Ten sam rodzaj

W tabelce poniżej pokazałem przykłady wyników porównania łańcuchów znaków za pomocą dwóch poznanych metod.

metoda/przykład wynik
String tekst = “kot”;
tekst.equals(“kot”) true
tekst.equals(“pies”) false
tekst.equals(“KOT”) false
tekst.equalsIgnoreCase(“kot”) true
tekst.equalsIgnoreCase(“pies”) false
tekst.equalsIgnoreCase(“KOT”) true

Albo, albo, czyli operator trójargumentowy (? :)

Na koniec warto wspomnieć o operatorze warunkowym, który ma taką postać:

wyrażenie ? wartośćP : wartośćF

W zależności od tego, czy wyrażenie jest prawdziwe czy nie, zostaje zwrócona wartośćP lub wartośćF.

Na przykład można go użyć w ten sposób:


System.out.println( liczba%2 == 0 ? "Parzysta" : "Nieparzysta");

I jeszcze nieco dłuższy przykład:

Główną zaletą operatora warunkowego jest to, że jest krótki i przejrzysty. Wady są takie, że pozwala na wybór tylko dwu możliwości (nie ma odpowiednika else if) a także jego zastosowanie jest w zasadzie ograniczone do zwracania wartości, nie pozwala na bezpośrednie wywołanie bloku kodu.

Operator negacji

Zestaw poznanych w operatorów logicznych należy jeszcze uzupełnić o operator negacji: !. Znak wykrzyknika stosowaliśmy przy sprawdzaniu czy jakieś wartości nie są równe, służył do tego operator !=. Wykrzyknik ma tu znaczenie zaprzeczenia i generalnie zaprzecza temu co zwraca argument, który poprzedza. Na przykład jeśli mamy wyrażenie 3 < 5 to zwraca ono wartość true, natomiast wyrażenie !(3 < 5) zwróci wartość przeciwną, czyli false. Operator ! można też zastosować w przypadku łańcuchów znaków, co także widać w poniższym przykładzie.

Zadania:

  1. Napisz program, który pobierze od użytkownika informację na temat chromosomów płciowych człowieka (XY lub XX) i na tej podstawie określi płeć (męska lub żeńska)

  2. Rozszerz program w ten sposób, żeby uwzględniał organizmy podane w poniższej tabeli :

organizm samica samiec
ssak XX XY
ryba XY XX
ptak XY XX
motyl XY XX
szczaw XX XYY

Uwaga: tabelka jest oczywiście uproszczona, np. nie wszystkie ssaki i motyle mają prezentowany sposób determinacji płci.

Rozwiązanie w następnej lekcji.


  • W starszych wersjach Javy (do 6) wyrażenie było ograniczone to typów byte, short, int oraz char.

Ta strona jest częścią materiałów do kursu “Programowanie w Javie z elementami bioinformatyki dla poczatkujących”. Pozostałe materiały znajdziesz tutaj

1 comment to Java [10] – Instrukcje wyboru cz. II

  • Mariusz

    Poniżej kod dla zadania 2go. Nie wiedziałem jak to zrobić w przypadku XYY, ale będę wiedział przeglądając kolejną lekcję.
    public class XXXY {
    public static void main(String args[]) {
    System.out.println(„Podaj chromosomy płciowe człowieka (XX lub XY)”);
    Scanner podaj = new Scanner(System.in);
    String plec = podaj.next();

    if (plec.equalsIgnoreCase(„XX”))

    {
    System.out.println(„ssak: samica, ryba: samiec, ptak: samiec, motyl: samiec, szczaw: samica”);
    }

    else if (plec.equalsIgnoreCase(„XY”))
    {
    System.out.println(„ssak: samiec, ryba: samica, ptak: samica, motyl: samica, szczaw: samiec”);

    }
    }
    }

Leave a Reply