Podstawy Java Część II www.mini.pw.edu.pl/~marcinbo
Pojęcia Wstępne Zadanie: Wyliczyć rozwiązanie układu 2 równań liniowych metodą wyznaczników Wersja uproszczona zakłada, że zawsze jest rozwiązanie
Pojęcia Wstępne Rozwiązanie A1. [Pobranie danych] pobierz a 1,a 2,b 1,b 2,c 1 i c 2 A2. [Wyliczenie W] W a 1 * b 2 - a 2 * b 1 A3. [Wyliczenie W x ] W x c 1 * b 2 - c 2 * b 1 A4. [Wyliczenie W y] W y a 1 * c 2 - a 2 * c 1 A5. [Wyznaczenie x] wypisz W x /W A6. [Wyznaczenie y] wypisz W y /W
import java.io.* ; public class uklad1 { public static void main(string[] args) { double a1,a2,b1,b2,c1,c2; Double W,Wx,Wy; String s; InputStreamReader stdin = new InputStreamReader(System.in); BufferedReader in = new BufferedReader(stdin); try{ System.out.println("Podaj a1:"); s=in.readline(); a1=double.parsedouble(s); System.out.println("Podaj a2:"); s=in.readline(); a2=double.parsedouble(s); System.out.println("Podaj b1:"); s=in.readline(); b1=double.parsedouble(s); System.out.println("Podaj b2:"); s=in.readline(); b2=double.parsedouble(s); System.out.println("Podaj c1:"); s=in.readline(); c1=double.parsedouble(s); System.out.println("Podaj c2:"); s=in.readline(); c2=double.parsedouble(s); }catch(ioexception e) { e.printstacktrace(); return; }catch(numberformatexception e) { e.printstacktrace(); return; } W=a1*b2-a2*b1; Wx=c1*b2-c2*b1; Wy=a1*c2-a2*c1; System.out.print("x="); System.out.println(Wx/W); System.out.print("y="); System.out.println(Wy/W); } }
Algorytmy zawierające jedynie stałą sekwencje instrukcji nie są w stanie rozwiązać większości problemów Możliwość warunkowego wykonania pewnych instrukcji dopuszcza instrukcja warunkowa, możliwość wykonania pewnych działań cyklicznie umożliwiają pętle Instrukcje sterujące to te, które decydują o kolejności wykonania instrukcji w algorytmie
Instrukcja warunkowa składnia: if(warunek) Instrukcja1 [else Instrukcaj2] Warunek jeżeli okaże się prawdziwy spowoduje wykonanie Instrukcji1 w p.p. wykona się Instrukcja2 Sekcja else jest opcjonalna, jej brak w przypadku nieprawdziwości Warunku powoduje przejście algorytmu do następnej po if instrukcji
Warunek Musi być zawarty w nawiasach Do zapisania warunku służą operatory logiczne Operatory logiczne nie zmieniają wartości zmiennych Proste operatory porównań można łączyć w celu zapisania bardziej skomplikowanych warunków Warunki if(0)... /*zawsze nieprawda*/ if(1)... /*zawsze prawda*/
Sprawdzanie równości == if(1==1)... /*prawda*/ if(2==1)... /*nieprawda*/ if( a == b )... /*nieprawda*/ a = 0 ; /*przypisanie wartości zmiennej*/ if(a==0)... /*prawda*/ if(a==2.8)... /*nieprawda*/ if(a==a+1)... /*nieprawda niezależnie od wartości a*/ Po obu stronach porównania mogą występować zmienne lub stałe oraz wyrażenia składające się z nich oraz operatorów arytmetycznych
Sprawdzanie nierówności!= if(1!=1)... /*nieprawda*/ if(2!=1)... /*prawda*/ if( a!= b )... /*prawda*/ a = 0 ; /*przypisanie wartości zmiennej*/ if(a!=0)... /*nieprawda*/ if(a!=2)... /*prawda*/ if(a!=a+1)... /*prawda niezależnie od wartości a*/ Po obu stronach porównania mogą występować zmienne lub stałe oraz wyrażenia składające się z nich oraz operatorów arytmetycznych
Sprawdzanie zależności większy, mniejszy if(1>1)... /*nieprawda*/ if(2<1)... /*nieprawda*/ a = 0 ; b = 3; if(a<0)... /*nieprawda*/ if(a<2,1345)... /*prawda*/ if(a>b+1)... /*nieprawda*/ Po obu stronach porównania mogą występować zmienne lub stałe oraz wyrażenia składające się z nich oraz operatorów arytmetycznych Znaki (typ char) też można porównywać if( b > a )... /*prawda*/
Sprawdzanie zależności większy równy, mniejszy równy if(1>=1)... /*prawda*/ if(2<=1)... /*nieprawda*/ a = 0 ; b = 2; if(a<=0)... /*prawda*/ if(a<=2,1345)... /*prawda*/ if(a>=b-2)... /*prawda*/ if( a >= w )... /*nieprawda*/ Po obu stronach porównania mogą występować zmienne lub stałe oraz wyrażenia składające się z nich oraz operatorów arytmetycznych
Negowanie warunku Każdy warunek można poprzedzić znakiem! co spowoduje jego odwrócenie np.: warunek a==b a>3 a<=b+8 tmp!=suma+1 negacja!(a==b)!(a>3)!(a<=b+8)!(tmp!=suma+1)
a, b i c to zmienne typu int Łączenie warunków równoważnych umożliwia operator && Warunek a==1&&b==3 jest prawdziwy tylko gdy zarówno prawda jest, że a==1 jak i b==3 Warunek a!=b&&a>3&&a<5 jest prawdziwy tylko gdy a jest liczba 4 i b nie jest równe 4 Łączenie warunków alternatywnych umożliwia operator Warunek c>5 c<1 jest prawdziwy jeżeli c>5 lub c <1 czyli dla liczb spoza zakresu <1,5> Warunek a>b+3 a<b-3 a==0 jest prawda dla a odległego od b o więcej niż 3 lub równego zero
Łączenie operatorów && i Operatory && są obliczane przed można to zmienić tylko poprzez użycie nawiasów Warunek a>3 a<-3&&b==a jest prawdą dla a>3 i dowolnego b oraz dla a i b równych i jednocześnie mniejszych od -3 Warunek (a>3 a<-3)&&b==a jest prawdą tylko dla a równego b i jednocześnie wartość obu zmiennych musi być spoza zakresu <-3,3> Nawiasy stosujemy też dla poprawy czytelności warunku Np.: ((a!=b)&&(a>3)&&(a<5))...
instrukcja blokowa. Pozwala zebrać grupę instrukcji w jedną całość i używać takiego bloku wszędzie tam gdzie wymagana jest tylko jedna instrukcja. Blok instrukcji rozpoczyna się znakiem { i kończy } Instrukcje wewnątrz nawiasów zwyczajowo piszemy wysunięte o 4 lub 8 spacji (tabulator) względem wcześniejszych instrukcji Przykład instrukcji blokowej i warunkowej :
/* zmienna a przyjmuje wartość 6*/ /* zmienna b przyjmuje wartość 0 */ if(b!=0) { }else System.out.print("Wynik dzielenia:"); System.out.println(a/b); 0!=0 to jest fałsz System.out.println("Blad dzielenia!");
/* zmienna a przyjmuje wartość 6*/ /* zmienna b przyjmuje wartość 2 */ if(b!=0) { }else System.out.print("Wynik dzielenia:"); System.out.println(a/b); 2!=0 to jest prawda System.out.println("Blad dzielenia!");
Można teraz poprawić program wyliczający rozwiązanie układu równań Wyeliminujemy przypadek dzielenia przez zero Dla W=0, Wx=0 oraz Wy=0 układ ma nieskończenie wiele rozwiązań Dla W=0 oraz Wx lub Wy <> 0 układ nie ma rozwiązania Wystarczy rozpatrzyć te warunki w kodzie
W=a1*b2-a2*b1; Wx=c1*b2-c2*b1; Wy=a1*c2-a2*c1; System.out.print("x="); System.out.println(Wx/W); System.out.print("y="); System.out.println(Wy/W); Te obliczenia będą prowadzić do błędów
... W=a1*b2-a2*b1; Wx=c1*b2-c2*b1; Wy=a1*c2-a2*c1; if(w==0){ if((wx==0)&&(wy==0)) System.out.println("Uklad ma wiele rozwiazan"); else System.out.println("Uklad jest sprzeczny"); }else{ } System.out.print("x="); System.out.println(Wx/W); System.out.print("y="); System.out.println(Wy/W);
Pętla for Pozwala wykonać pewną instrukcje wielokrotnie (także instrukcję blokową) Można z góry określić ile razy instrukcja będzie wykonywana lub ustalić warunek końca pętli właściwość STOP Programista musi zadbać o to aby pętla nie wykonywała się bez końca
Pętla for składnia: for(instrukcja1;warunek;instrukcja2) Instrukcja3; przed wykonaniem pętli jest wykonywana instrukcja1 Aby pętla mogła zostać wykonana Warunek musi być spełniony (prawdziwy) Po każdym wykonaniu Instrukcji3 w pętli (po każdej iteracji) wykonywana jest instrukcja2
for w języku naturalnym A1.[inicjalizacja] wykonaj Instrukcja1 A2.[Warunek] Jeżeli Warunek nie jest spełniony przejdź do punku A5 A3.[Iteracja] wykonaj Instrukcja3 A4.[Iteracja] wykonaj Instrukcja2 i przejdź do punku A2 A5.[Koniec pętli]
Warunek sprawdzany w pętli powinien dotyczyć zmiennych modyfikowanych w Instrukcji3 lub Instrukcji2 inaczej pętla może być nieskończona. Najczęściej pętla for używana jest do wykonania instrukcji określoną ilość razy Do odliczania kolejnych razów używa się zmiennej pomocniczej
Wypiszmy w pętli liczby od 1 do 10,000 Pomysł wypisania 10,000 instrukcji cout<< raczej odpada Zostaje pętla jako jedyne rozsądne rozwiązanie int i; for(i=1;i<=10000;i++) System.out.println(i);
Zadanie: Pobrać 10 liczb całkowitych od użytkownika Wyznaczyć najmniejszą i największą z nich Wypisać wynik na ekranie Zapamiętamy w zmiennej max największą dotychczas znalezioną liczbę, podobnie w zmiennej min najmniejszą Należy użyć pętli for do pobierania kolejnej liczby i sprawdzania za pomocą instrukcji warunkowych czy nie jest ona większa od dotychczas znanego max lub mniejsza od min
import java.io.*; public class petla1 { public static void main(string[] args) { int min,max,liczba,i; String s; InputStreamReader stdin = new InputStreamReader(System.in); BufferedReader in = new BufferedReader(stdin); try{ System.out.println("Podaj 10 liczb calkowitych"); s=in.readline(); } liczba=integer.parseint(s); max=min=liczba; for(i=1;i<10;i++) { s=in.readline(); Nadanie wartości początkowych min i max liczba=integer.parseint(s); if(liczba>max) max=liczba; else if(liczba<min) min=liczba; } }catch(exception e) { e.printstacktrace(); return; } System.out.print("Maksymalna wartosc to:"); System.out.println(max); System.out.print("Minimalna wartosc to:"); System.out.println(min); } Ta pętla wykona się dokładnie 9 razy
Pętla while Pozwala wykonać pewną instrukcje wielokrotnie (także instrukcję blokową) Ilość wykonań jest kontrolowana warunkiem Programista musi zadbać o to aby pętla nie wykonywała się bez końca, czyli musi postawić warunek tak aby zmian dokonywane w pętli spowodowały jego niespełnienie.
Pętla while składnia: while(warunek) Instrukcja; Aby pętla mogła zostać wykonana Warunek musi być spełniony (prawdziwy) Nie ma tu instrukcji wykonywanych przed pętlą ani po każdej iteracji, ale programista może zawsze umieścić instrukcje przed pętlą lub wewnątrz Instrukcji (o ile jest to blok)
while w języku naturalnym A1.[Warunek] Jeżeli Warunek nie jest spełniony przejdź do punku A3 A2.[Iteracja] wykonaj Instrukcję i przejdź do punku A1 A3.[Koniec pętli]
Instrukcje for i while mogą być używane zamiennie (po odpowiednich modyfikacjach kodu) Tam gdzie ilość wykonań pętli jest z góry znana zazwyczaj używamy for Tam gdzie o ilości iteracji decyduje warunek zazwyczaj wybieramy for lub while na podstawie wygody użycia danej notacji
Wypiszmy w pętli liczby od 1 do 10,000 tym razem z użyciem pętli while int i; i=1; while(i<=10000){ cout<<i<<endl; i++; }
Zadanie: Pobrać liczby całkowite od użytkownika Liczb może być dowolnie dużo, podanie zera kończy pobieranie danych Wyznaczyć sumę podanych liczb Wypisać wynik na ekranie Zapamiętamy w zmiennej suma sumę wszystkich wczytanych do tej pory liczb Należy użyć pętli while do pobierania kolejnych liczb aż do podania zera
import java.io.*; public class petla2 { public static void main(string[] args) { int suma; int liczba; String s; InputStreamReader stdin = new InputStreamReader(System.in); BufferedReader in = new BufferedReader(stdin); try{ System.out.println("Podaj liczby, zero konczy:"); suma=0; s=in.readline(); liczba=integer.parseint(s); while(liczba!=0) { suma+=liczba; s=in.readline(); liczba=integer.parseint(s); } }catch(exception e) { e.printstacktrace(); return; } System.out.print("Suma liczb to:"); System.out.println(suma); } }
Pętla do while Podobnie jak pętla while pozwala wykonywać instrukcję tak długo jak długo warunek w pętli jest prawdą. Różnica polega na tym, że warunek sprawdzany jest na końcu każdej iteracji, a nie na początku. Oznacza to, że pętla do while wykona się co najmniej raz
Pętla do while składnia: do Instrukcja; while(warunek) Aby pętla mogła zostać powtórzona Warunek musi być spełniony (prawdziwy) do while w języku naturalnym A1.[Iteracja] wykonaj Instrukcję A2.[Warunek] Jeżeli Warunek jest spełniony przejdź do punku A1
Instrukcje for i while oraz do while mogą być używane zamiennie (po odpowiednich modyfikacjach kodu) O tym czy użyć while czy do while decyduje wygoda zapisu (przykłady na następnych slajdach) Aby zapisać więcej niż jedną instrukcje w pętli do while można zastosować instrukcję blokową.
Wypiszmy w pętli liczby od 1 do 10,000 tym razem z użyciem pętli do while int i; i=1; do{ cout<<i<<endl; i++; }while(i<=10000);
import java.io.*; public class petla3 { public static void main(string[] args) { int suma; int liczba; String s; InputStreamReader stdin = new InputStreamReader(System.in); BufferedReader in = new BufferedReader(stdin); try{ System.out.println("Podaj liczby, zero konczy:"); suma=0; do{ Zapisujemy tylko raz s=in.readline(); liczba=integer.parseint(s); suma+=liczba; }while(liczba!=0); }catch(exception e) { e.printstacktrace(); return; } System.out.print("Suma liczb to:"); System.out.println(suma); } } Zero nie zmienia wyniku
Tablice
Tablice Proste zmienne typów int, char i double nie wystarczają do opisu wszystkich potrzebnych danych przechowywanych w komputerze Bardziej złożone struktury danych bazują na prostych typach jako składowych Najważniejszym typem złożonym jest tablica
Tablice Tablice pozwalają przechowywać duże ilości danych tego samego typu Zadanie: przechować w pamięci 2000 liczb pobranych od użytkownika. Zadeklarowanie 2000 zmiennych a1,a2,...,a2000 nie jest dobrym rozwiązaniem Należy użyć tablicy jednowymiarowej o rozmiarze 2000
Tablice A[0] A[1] A[2]... A[1999] int A[2000]; Tablica A posiada miejsce do przechowania 2000 liczb typu int Pierwsza liczna dostępna jest pod indeksem 0 a ostatnia pod indeksem 1999 Dostęp do liczby uzyskujemy poprzez indeksowanie oraz nazwę tablicy
Tablice int A[100]; A[0] = 5; //przypisanie pierwszej komórce wartości 5 A[99] = 9 ; //przypisanie wartości ostatniej komórce tmp = A[56] ; //odczyt 57 komórki w tabeli zm2 = A[i] ; //odczyt wartości z i+1 komórki W tablicy indeksy liczymy od 0 nie od 1!
Tablice W tablicy elementy są umieszczone sekwencyjnie co umożliwia łatwe dostęp do następujących po sobie elementów. Zadanie: napisać algorytm wyznaczający najmniejszą wartość zapisaną w danej stuelementowej tablicy liczb. for(min=a[0],i=1;i<100;i++) if(a[i]<min) min = A[i]; Nie da się tego łatwo zapisać używając 100 zmiennych!!! (różnica jest tylko w zapisie nie w działaniu)
Tablice Tablice deklarujemy, podobnie jak zwykłe zmienne, na początku kodu. typ nazwa[rozmiar] ; Typ to dowolny z typów prostych, takiego typu będą wszystkie komórki w tabeli; Rozmiar to ilość komórek; Jeśli tablica ma zawierac obiekty deklarujemy ja: typ nazwa[] = new typ [rozmiar];
Tablice class ArrayTest { public static void main(string[] args) { int i; String s[]={"styczen","luty","marzec","kwiecien"}; System.out.print("Rozmiar tablicy : "); System.out.println(s.length); for(i=0;i<s.length;i++){ System.out.println(s[i]); } } } class ArrayTest2 { public static void main(string[] args) { int i; Double tab[]= new Double[10]; for(i=0;i<10;i++) tab[i]=i*java.lang.math.pi ; for(i=0;i<10;i++) System.out.println(tab[i]); } }
Tablice Można zadeklarować tablicę tablic, powstają w ten sposób tablice 2-wymiarowe W deklaracji podajemy 2 wymiary, najpierw liczbę wierszy, potem kolumn. Każdy wiersz jest tablicą jednowymiarową int Tab[3][15]; // 3 wiersze po 15 komórek tablica 3 tablic 15 elementowych indeksowanie podobnie jak deklaracja t.j. wiersz, kolumna : Tab[0][0], Tab[1][14],Tab[2][3]
Tablice import java.util.random ; class ArrayTest3 { private static final int SIZE = 10; public static void main(string[] args) { Integer i,j; Random rand = new Random(); Integer tab[][]= new Integer[SIZE][]; for(i=0;i<size;i++) tab[i]=new Integer[SIZE]; for(i=0;i<size;i++) { for(j=0;j<size;j++) { tab[i][j]=rand.nextint(10); }} for(i=0;i<size;i++) { for(j=0;j<size;j++) { System.out.print(tab[i][j] + " "); } System.out.print("\n"); }}}