Spis treści
Typ String, przechowujący ciągi znaków, pozwala na pobranie z niego znaku o podanym indeksie.
Indeksy znaków zaczynają się od 0, a nie od 1, więc pierwszy znak przechowywany w zmiennej typu String znajduje się pod indeksem 0, a indeks ostatniego znaku to liczba znaków pomniejszona o 1.
Dla przykładu, mając następującą zmienną typu String:
String komunikat = "Ala ma kota";
Znaki składające się na wartość zmiennej komunikat mają następujące indeksy:
Indeks | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
Litera | A | l | a | m | a | k | o | t | a |
Zauważmy, iż:
- pierwszy znak, czyli 'A', ma indeks 0, a nie 1.
- ostatni znak, czyli 'a', ma indeks równy długości całego stringu (tzn. liczby znaków, które zawiera) minus 1, czyli 10 (ponieważ wszystkich znaków jest 11). Wynika to z faktu, że indeksy rozpoczynają się od 0, a nie 1.
Aby otrzymać znak znajdujący się na danej pozycji, stosujemy metodę charAt, której podajemy jako argument indeks znaku, który chcemy pobrać.
Spójrzmy na przykład, w którym wypisujemy na ekran pierwszy znak zmiennej typu String:
public class WypiszPierwszyZnakCharAt { public static void main(String[] args) { String komunikat = "Witaj!"; System.out.println(komunikat.charAt(0)); } }
Ten program wypisuje na ekran jedną literę:
Skorzystaliśmy w nim z metody charAt do pobrania pierwszego znaku w stringu, czyli tego, który ma indeks 0. Znak jest zwracany i służy jako argument dla instrukcji wypisującej tekst na ekran.
A co stanie się, jeżeli podamy nieprawidłowy indeks? Na przykład, zapytamy o znak o indeksie 100, gdy zmienna typu String będzie zawierała krótszy tekst?
public class WypiszZnakCharAtNieprawidlowyIndeks { public static void main(String[] args) { String komunikat = "Witaj!"; System.out.println(komunikat.charAt(100)); } }
Ten program skompiluje się bez błędów, jednak po uruchomieniu go wystąpi błąd i działanie programu zakończy się. Na ekranie zobaczymy następujący błąd:
Błąd wystąpił, ponieważ podany indeks jest nieprawidłowy – w zmiennej komunikat nie ma znaku o indeksie 100, ponieważ string ten zawiera jedynie 6 znaków. Komunikat błędu jest jasny: String index out of range: 100.
Zwróćmy uwagę na bardzo ważny aspekt tego programu. Program skompilował się bez błędów, tzn. kompilator poprawnie nie stwierdził żadnych problemów w kodzie.
Problem w programie nie wynika z błędnej składni programu, którą kompilator jest w stanie wychwycić – problem wynika z logicznego błędu, który uwidacznia się dopiero po uruchomieniu programu.
Skoro znaki w stringach mają indeksy, które są kolejnymi liczbami całkowitymi, to moglibyśmy skorzystać z funkcjonalności pętli for, która w prosty sposób umożliwi nam odwoływanie się do kolejnych znaków w stringu. Będziemy jednak potrzebować sposobu, by dowiedzieć się, z ilu znaków łańcuch tekstowy się składa.
W jednym z zadań do rozdziału trzeciego o zmiennych (Liczba znaków w słowie) należało skorzystać z metody, która zwraca liczbę znaków przechowywanych w zmiennej typu String. Ta metoda to length.
Spójrzmy na użycie obu metod, charAt oraz length, by "rozstrzelić" zapisany napis (tzn. wstawić po każdym znaku tekstu dodatkową spację):
public class CharAtILengthPrzyklad { public static void main(String[] args) { String tekst = "Ala ma kota"; for (int i = 0; i < tekst.length(); i++) { System.out.print(tekst.charAt(i) + " "); } } }
Użyliśmy metody length, by pobrać długość tekstu, a także metody charAt, by pobrać znak na danej pozycji (pamiętajmy, że pierwszy znak ma indeks 0!). Wynik:
Zastosowana pętla for przechodzi po wszystkich liczbach, które są indeksami znaków w stringu tekst, zaczynając od 0. Zauważmy, że warunek pętli korzysta z operatora < a nie <=. Gdybyśmy skorzystali z operatora <=, to zmienna i w ostatniej iteracji miałaby wartość 11 – tyle wynosi liczba znaków w zmiennej tekst i taką wartość zwraca tekst.length() – spowodowałoby to błąd, ponieważ indeks ostatniego znaku to 10, a nie 11 – dlatego musieliśmy skorzystać z operatora <.
Spójrzmy na jeszcze jeden przykład – wypisujemy w nim tekst od końca:
public class TekstOdKonca { public static void main(String[] args) { String tekst = "Ala ma kota"; for (int i = tekst.length() - 1; i >= 0; i--) { System.out.print(tekst.charAt(i)); } } }
Zwróćmy tutaj uwagę, iż zmienna i, zdefiniowana w pętli, zaczęła od indeksu ostatniego znaku w zmienej tekst, którego indeks równy jest liczbie znaków w tym stringu minus 1, o czym już wspominaliśmy. W kroku pętli zmniejszamy ten indeks o 1. W ciele pętli wypisujemy znak pod aktualnym indeksem, co skutkuje, że idziemy od końca tekstu do początku. Pętla kończy działanie, gdy zmienna i przekroczy indeks pierwszego znaku, czyli 0.
Wynik:
Porównywanie znaków zwracanych przez charAt¶
Wykorzystywana przez nas metoda charAt zwraca pojedynczy znak, czyli wartość typu podstawowego char, a nie łańcuch tekstowy typu String.
Powoduje to, że możemy porównywać znaki zwracane przez metodę charAt z innymi znakami za pomocą operatora ==. Nie musimy, a nawet nie możemy, stosować w takim przypadku metody equals. Spójrzmy na przykład programu, który zlicza samogłoski w wyrazie podanym przez użytkownika:
import java.util.Scanner; public class ZliczSamogloski { public static void main(String[] args) { System.out.println("Podaj slowo:"); String slowo = getString(); int liczbaSamoglosek = 0; for (int i = 0; i < slowo.length(); i++) { char znak = slowo.charAt(i); if (znak == 'a' || znak == 'e' || znak == 'i' || znak == 'u' || znak == 'y' || znak == 'o') { liczbaSamoglosek++; } } System.out.println( "Slowo " + slowo + " ma " + liczbaSamoglosek + " samoglosek." ); } public static String getString() { return new Scanner(System.in).next(); } }
Program pobiera od użytkownika słowo i w pętli for przechodzi przez każdy znak, z którego się składa. Aktualny znak przypisujemy do zmiennej o nazwie znak, którą następnie przyrównujemy do samogłosek za pomocą operatora ==. Nie korzystamy z metody equals, ponieważ w tym przypadku nie działamy na stringach, lecz na znakach.
Warunek sprawdzający, czy znak to samogłoska, to złożone wyrażenie wykorzystujące operator logiczny || (lub) – jeżeli aktualny znak będzie którąkolwiek z samogłosek, to warunek będzie spełniony, więc zwiększymy liczbę znalezionych samogłosek o jeden za pomocą instrukcji liczbaSamoglosek++;.
Po przejściu przez całe słowo, wypisujemy na ekran informację o znalezionej liczbie samogłosek.
Przykładowe uruchomienie tego programu: