Prawo Murphy'ego: Prawidłowo napisany tekst pojawi się tylko wtedy, kiedy napiszesz go ręcznie.
Część 3.6. Przykłady programów Javy

1. Parametry metody main

Zaczniemy od prostego programu, którego jedynym zadaniem będzie wyświetlenie parametrów. Zastanawiałeś się zapewne po co zawsze w metodzie main podajemy parametr String args[]? Jest to tablica parametrów przekazanych do programu podczas jego uruchamiania. Każdy łańcuch znaków, zakończony spacją, podany po nazwie uruchamianego programu wstawiany jest do tej tablicy na kolejną pozycję. W ten sposób możemy uruchamianemu programowi przekazać pewne dane już w momencie uruchomienia.

class Parametry
{ public static void main (String args[])
  { for (int i = 0; i < args.length; i++)
        System.out.println ("args[" + i + "] = " + args[i]);
  }
}

Po napisaniu tego programu uruchom go w następujący sposób:

java  Parametry  ala ola ela

Program powinien na ekranie wyświetlić:

args[0] = ala
args[1] = ola
args[2] = ela

2. Wczytywanie liczb całkowitych i rzeczywistych z klawiatury

Kolejny program pokazuje, jak w Javie można wczytywać dane z klawiatury. Program służy do wczytywania pary liczb: najpierw całkowitej, a następnie rzeczywistej. Wczytywanie powtarzane jest do moment, gdy choć jedna z wprowadzonych liczb będzie zerem.

Wczytywanie danych z klawiatury nie należy do czynności prostych. Wymaga użycia aż trzech klas: InputStreamReader, której instancją jest System.in, oraz BufferedReader i StreamTokenizer. Wzzystkie one zadeklarowane sa w pakiecie java.io, stąd konieczność dołączenia tego pakietu do naszego programu.

//dołączenie pakietu java.io
import java.io.*;

public class CzytanieLiczb
{ public static void main (String args[])
  { int    a = 1;
    double b = 1;
    // deklaracja obiektów niezbędnych do wczytywania danych z klawiatury
    Reader          r   = new BufferedReader (new InputStreamReader(System.in));
    StreamTokenizer inp = new StreamTokenizer(r);
      
    // blok try jest konieczny ze względu na użycie metody nextToken()
    // bez użycia tego bloku wystąpiłby błąd kompilacji
    try
    {  while (a != 0 && b != 0)
       {  System.out.print("\nPodaj liczbę całkowitą: ");
          while (inp.nextToken() != StreamTokenizer.TT_NUMBER)
                // wczytywanie do momentu otrzymania poprawnej liczby całkwitej
                { System.out.println("Blad wprowadzania\nPodaj liczbe całkowita:"); }
           a = (int) inp.nval;             // konwersja danych na typ całkowity

           System.out.print("Podaj liczbe rzeczywista: ");
           while (inp.nextToken() != StreamTokenizer.TT_NUMBER)
                // wczytywanie do momentu otrzymania poprawnej liczby rzeczywistej
                { System.out.println("Blad wprowadzania\nPodaj liczbe rzeczywista:"); }
           b = (double) inp.nval;          // konwersja danych na typ rzeczywisty

           System.out.println("Liczba calkowita = " + a + ", liczba rzeczywista = " + b);
       }
    }

    // konieczne jako zamkniecie bloku try
    catch (IOException e)
    { ; }
  }
}

Zobacz kilka przykładów działania tego programu. Zwróć uwagę na różne możliwości wpisywania danych. Program zawsze czyta cały wiersz, a potem dopiero dzieli go na tokeny (element, liczby, ...).

3. Obliczanie silni

Napiszemy teraz program obliczający i wyświetlający silnię (n! = 1*2*3*...*n) liczb od 0 do 20. Program sam w sobie dość banalny. Zwróć jednak uwagę na rekurencyjne wywołanie metody silnia.
class Silnia
{ public static void main (String args[])
  { long x;

    for (int n=0 ; n<=20 ; n++)
    { x = silnia(n);
      System.out.println (n + "! = " + x);
    }
  }

  static long silnia (int n)
  { long wynik;

    // metoda wywołuje sama siebie ze zmniejszoną o 1 wartością argumentu
    // aż do momentu, dgy przekazany argument będzie <= 1
    if (n > 1) wynik = silnia( n-1) * n;
    else       wynik = 1;
    return wynik;
  }
}

4. Największy wspólny podzielnik i najmniejsza wspólna wielokrotność

Ten program wczytuje parę liczb naturalnych i oblicza ich największy wspólny podzielnik i najmniejszą wspólną wielokrotność. Zwróć uwagę, że do wczytania obu liczb naturalnych wykorzystywana jest jedna i ta sama metoda: czyni to program bardziej zwięzłym, czytelnym i efektywniejszym.
import java.io.*;

class NwwNwp
{ public static void main (String args[])
  { int n1, n2, n;

    n1 = LiczbaNaturalna();
    n2 = LiczbaNaturalna();

    if (n1 > n2)
	{ n  = n1;
      n1 = n2;
      n2 = n;
	}
    n = n2;

    while (n % n1 !=0)
    { n += n2;
    }
    System.out.println("NWW = " + n);

    while (n1 != n2)
    { if (n1 > n2)  n1 -= n2;
      else          n2 -= n1;
    }
    System.out.println("NWP = " + n1);
  }

  static int LiczbaNaturalna()
  { int n = 0;
    Reader          r   = new BufferedReader(new InputStreamReader(System.in));
    StreamTokenizer inp = new StreamTokenizer(r);
      
    try
    {  while (n <= 0)
       {  System.out.print("Podaj liczbe naturalna: ");
          while (inp.nextToken() != StreamTokenizer.TT_NUMBER)
               { System.out.println("Liczba musi byc > 0\nPodaj liczbe naturalna:"); }
          n = (int) inp.nval;
       }
    }

    catch (IOException e)
    { ; }

    return n;
  }
}

5. Sortowanie tablicy jednowymiarowej

Zadaniem kolejnego programu jest posortowanie wektora (tablicy jedno wymiarowej) liczb całkowitych. Program najpierw wczytuje rozmiar wektora, a następnie wszystkie jego elementy. Po zakończeniu wczytywania następuje sortowanie wektora i wyswietlenie wszystkich jego elementów.

Program wykorzystuje znaną już metodę rekurencyjną w metodzie sort oraz metodę służącą do wczytywania danych z klawiatury. Zwróć szczególną uwagę na dynamiczne przydzielanie pamięci dla wektora danych: przydział pamięci następuje dopiero po wczytaniu ilości elementów wektora, a tworzony wektor będzie zajmował dokładnie tyle pamięci, ile jest konieczne do przechowania podanej ilości elementów.

import java.io.*;

class SortowanieTablicy
{ static int Len;
  static int T[];
  
  public static void main (String args[])
  { Len = CzytajLiczbe(-1);
    T = new int [Len];

    System.out.println("Podaj elementy tablicy");

    for (int i=0 ; i<Len ; i++) 
    { T[i] = CzytajLiczbe(i);
    }

    sort(0, Len-1);

    System.out.println("\n\nPosortowana tablica:");
    for (int i=0 ; i<Len ; i++) 
    { System.out.print(T[i] + ", ");
    }
  }

  static int CzytajLiczbe(int i)
  { int n = 0;
    String s;
    Reader          r   = new BufferedReader(new InputStreamReader(System.in));
    StreamTokenizer inp = new StreamTokenizer(r);
      
    // ustawienie wyświetlanego komunikatu w zależności od tego, co jest wczytywane:
    // inny dla rozmiaru wektora i inny dla jego elementów
    if (i == -1) s = new String("Podaj ilosc elementów w tablicy: ");
    else         s = new String("Podaj " + i + " element tablicy: ");
    try
    {  while (true)
       {  System.out.print(s);
          while (inp.nextToken() != StreamTokenizer.TT_NUMBER)
               { System.out.println("Blad! " + s); }
          n = (int) inp.nval;
          // dla rozmiaru wektora wartość musi być dodatnia
          // dla elementów wektora - może być dowolną liczbą całkowitą
          if (i == -1  &&  n > 0  ||  i >= 0) break;
       }
    }
    catch (IOException e)
    {;}

    return n;
  }

  static void sort(int min, int max)
  { int i = min , j = max, x, y = (int)((min+max)/2);
    x = T[y];

    do
    { while (T[i] < x  &&  i < max)	i++;
      while (x < T[j]  &&  j > 0 )	j--;
      if (i <= j)
      { y    = T[i];
        T[i] = T[j];
        T[j] = y;
        i++;
        j--;
      }
    } while (i <= j);

    // rekurencyjne wywoływanie metody, aż do zakończenia sortowania
    if (min < j) sort(min, j);
    if (i < max) sort(i, max);
  }
}

6. Sumowanie wierszy i kolumn tablicy dwuwymiarowej

Na zakończenie program operujący na macierzy (tablicy dwuwymiarowej). Aby uniknąć wprowadzania wielu danych elementy macierzy są generowane losowo: służy do tego metoda Math.random(), która generuje liczby losowe z zakresu [0, 1>. Po wygenerowaniu wszystkich elementów macierzy następuje jej wyświetlenie z jednoczesnym sumowaniem wartości w każdym wierszu i każdej kolumnie.
public class Tablica2D
{  public static void main (String args[])
   {  int x, y, T[][] = new int [5][5];
      String txt;
      int suma;

      // generowanie elementów macierzy: liczb losowych z przedziału [0, 500]
      for (y = 0 ; y <= 4 ; y++)
          for (x = 0 ; x <= 4 ; x++)
              T[x][y] = (int) (Math.round(Math.random() * 500));

      // wyświetlanie macierzy z sumowaniem wartości w wierszach
      for (y = 0 ; y <= 4 ; y++)
      {  suma = 0;
         for (x = 0 ; x <= 4 ; x++)		
         {  suma += T[x][y];
            txt = Integer.toString (T[x][y]);     // konwersja liczby na łańcuch znaków

            // pętla uzupełniająca wyświetlany tekst spacjami z przodu:
            // ma to zagwarantować jednakową ilość miejsc dla każdej liczby
            while (txt.length() < 5)
                  { txt = " " + txt; }
            System.out.print (txt);
         }
         txt = Integer.toString (suma);           // konwersja liczby na łańcuch znaków

        // pętla uzupełniająca wyświetlany tekst spacjami z przodu:
        // ma to zagwarantować jednakową ilość miejsc dla każdej liczby
         while (txt.length() < 5)
                { txt = " " + txt; }
         System.out.println ("| " + txt);
      }

      System.out.println ("--------------------------");

      // sumowanie wartości w kolumnach macierzy
      for (x = 0 ; x <= 4 ; x++)
      {  suma = 0;
         for (y = 0 ; y <= 4 ; y++)		
         {  suma += T[x][y];
         }
         txt = Integer.toString (suma);             // konwersja liczby na łańcuch znaków

        // pętla uzupełniająca wyświetlany tekst spacjami z przodu:
        // ma to zagwarantować jednakową ilość miejsc dla każdej liczby
         while (txt.length() < 5)
              {txt = " " + txt;}
         System.out.print (txt);
      }
   }
}
« wstecz   dalej »