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: