2. Rozbiór tekstów
Bardzo często w programowaniu występują sytuacje, gdy trzeba rozbić, rozłożyć
jakiś tekst (napis) na poszczególne występujące w nim symbole (np. słowa).
W przykładzie z liczbami separatorami będą spacje. Do wyłuskiwania symboli z łańcuchów znakowych służy klasa StringTokenizer z pakietu java.util.
Po to by dokonać rozbioru tekstu - tworzymy obiekt klasy StringTokenizer,
podając jako argument konstruktora - tekst do rozbioru np. String expr = "21 + 21"; StringTokenizer st = new StringTokenizer(expr);
Ta postać konstruktora zakłada domyślnie, że separatorami są znaki z następującego zestawu
Wyłuskiwanie symboli odbywa się sekwencyjnie poczynając od początku łańcucha. Służy temu metoda nextToken(), która zwraca kolejny symbol jako String. Pierwsze wywołanie tej metody
zwróci pierwszy symbol, następne - będą zwracać kolejne symbole łańcucha.
String s1 = st.nextToken(); // napis "21" String s2 = st.nextToken(); // napis "+" String s3 = st.nextToken(); // napis "21"
Gdy nie ma już symboli "do zwrotu" - wywołanie nextToken() spowoduje powstanie wyjątku NoSuchElementException. while (st.hasMoreTokens()) { Sring s = st.nextToken(); // ... tu coś robimy z s }
Wiedząc to wszystko można teraz napisać program, który w oknie dialogowym
prosi użytkownika o wprowadzeia liczby cąłkowitej, spacji, operatora, spacji
i drugiej liczby i wykonuje żądaną operację arytmetyczną na tych dwóch liczbach. Przed lekturą dalszego tekstu proszę to zadanie rozwiązać samodzielnie
Rozwiązanie: import java.util.*; import javax.swing.*; public class Oper { public static void main(String[] args) { String normalQuest = "Liczba1 op Liczba2", errorQuest = "Wadliwe dane. Jeszcze raz.\n" + normalQuest, quest = normalQuest; String expr; while ((expr = JOptionPane.showInputDialog(quest)) != null) { StringTokenizer st = new StringTokenizer(expr); if (st.countTokens() != 3) { quest = errorQuest; continue; } String snum1 = st.nextToken(), sop = st.nextToken(), snum2 = st.nextToken(); int num1 = Integer.parseInt(snum1), num2 = Integer.parseInt(snum2), res = 0; char op = sop.charAt(0); switch (op) { case '+' : res = num1 + num2; break; case '-' : res = num1 - num2; break; case '*' : res = num1 * num2; break; case '/' : res = num1 / num2; break; default: { quest = errorQuest; continue; } } JOptionPane.showMessageDialog(null, "Wynik = " + res); quest = normalQuest; } System.exit(0); } }
Inna postać konstruktora klasy StringTokenizer pozwala na określenie zbioru
separatorów, które będą służyć do wyróżniania symboli. Przed lekturą dalszego tekstu proszę to zadanie rozwiązać samodzielnie
Możliwe rozwiązanie: import java.util.*; public class Words { private String[] words; // tablica slów private String maxLenWord; // słowo o max długości private String minLenWord; // słowo o minimalnej długości // Konstruktro public Words(String txt) { // Uwzględniamy bogaty zestaw separatorów słów StringTokenizer st = new StringTokenizer(txt, " \t\n\r\f.,:;()[]\"'?!-{}"); words = new String[st.countTokens()]; // utworzenie tablicy słów int maxL = 0; // max dlugość int minL = 10000; // min długość int i = 0; // indeks w tablicy while (st.hasMoreTokens()) { // dopóki są słowa String s = st.nextToken(); int len = s.length(); if (len > maxL) { // maksymalna długość ? maxL = len; maxLenWord = s; } if (len < minL) { // minimalna długość ? minL = len; minLenWord = s; } words[i++] = s; // słowo -> do tablicy; zwiększenie indeksu } } // Zwraca liczbę słów public int getWordsCount() { return words.length; } // Zwraca i-te słowo (liczymy od 1) // jeśli podano wadliwy indeks - zwraca null public String getWord(int i) { return (i < 1 || i > words.length) ? null : words[i-1]; } // Zwraca tablicę slów public String[] getWords() { return words; } // Zwraca słowo o max długości public String getMaxLenWord() { return maxLenWord; } // Zwraca słowo o min długości public String getMinLenWord() { return minLenWord; } }
I klasa testująca: import javax.swing.*; class TestWords { public static void main(String[] args) { String txt; while ((txt = JOptionPane.showInputDialog("Wpisz tekst")) != null) { Words w = new Words(txt); int n = w.getWordsCount(); say("Liczba słów: " + n); say("Kolejne słowa: "); for (int i=1; i <= n; i++) say(w.getWord(i)); say("Słowo o numerze n+1: " + w.getWord(n+1)); say("Kolejne słowa: "); String[] wrds = w.getWords(); for (int i=0; i < wrds.length; i++) say(wrds[i]); say("Najdluższe słowo: " + w.getMaxLenWord()); say("Najkrótsze słowo: " + w.getMinLenWord()); } System.exit(0); } static void say(String s) { System.out.println(s); } } Klasa StringTokenizer dostarcza programiście jeszcze pewnych dodatkowych
możliwości (np. zmianę separatorów pomiędzy kolejnymi operacjami wyłuskiwania
symboli; zwracanie nie tylko symboli, ale i separatorów w wyniku odwołania
nextToken()).
|