[AUG] Projekt semestralny – wersja demo

Początek mojego projektu semestralnego z AUG (analiza pliku Java z klasą, ustalenie jakie ma zmienne, metody, po czym dziedziczy i co implementuje).

Wykład na temat bisona:
https://edux.pjwstk.edu.pl/mat/229/lec/frames-jfa-main-node14.html

Trochę czytelniejszy przykład:
http://fhoerni.free.fr/comp/bison_flex.html

——————————————-

A teraz mój kod. Co robi? Wczytuje pierwsze linijki pliku javy, czyli np. ‚package cos.cos.aaa;’ i wiele linii ‚import cos.cos.xxxx;’ lub z gwiazdką na końcu ‚import cos.cos.*;’

Oto rysunki automatów które potem zrealizowałem w bisonie:

bison

 

A teraz kod z komentarzami:
parser.y (bison)

%{
	#include <stdio.h>
	#include <strings.h>
%}
/* w tej czesci definiujemy zmienne i struktury z jakich mamy zamiar korzystac w naszym programie */

/*
pod spodem zmienna do przechowywania danych przekazywanych z flex'a
oprocz 'tokenow' jakie dostajemy z flex'a czasem chcemy tez przekazac ich wartosc

w moim przypadku oprocz tego, ze chce przekazac to,
ze trafilem na 'IDENTIFIER' (nazwe zmiennej/klasy/metody/pakietu)
to chce tez wiedziec jak sie ten identifier nazwywal (nazwa zmiennej/...)
(wiecej info w nastepnym komentarzu)
*/
%union
{
	char	*sval;
};
/*
jak widac IDENTIFIER ktory oprocz samego wystapienia 'zmiennej'
informuje mnie tez o jej nazwie ma przed soba
nazwe zmiennej w ktorej bedzie przechowywana nazwa
(w flex'ie tez trzeba to specjalnie obsluzyc, zeby zapamietac ta nazwe)
wiecej informacji o obsludze tego w komenatrzu o tytule 'POKAZANIE IDENTIFIER'
*/

%token <sval> IDENTIFIER
%token PACKAGE
%token IMPORT
%token DOT
%token STAR
%token DECNUMBER
%token SEMICOLON
/* powyzej zdefiniowalem 'tokeny' ktore moge zwracac [np. return(STAR); ]
z flex'a i interpretowac ich kolejnosc w bisonie*/
%%
/* w tej sekcji zapisuje reguly
/* STEP 1 */
/* najpierw wczytuje 0 lub 1 'package'  i przechodze dalej */
input1		: package1 input2
    		;

/* STEP 2 */
/* teraz wczytuje 0 do nieskonczonosci 'import' i przechodze dalej */
input2		: import0 input3
		;

/* STEP 3 */
/*
wypisuje 'koniec', normalnie przeszedl bym tutaj do wczytywanie nazwy klasy,
ale calego kodu programu jeszcze nie mam..
*/
input3		: {printf("KONIEC\n");}
		;

/* package - wczytanie 0 lub 1 */
package1	: PACKAGE {printf("package\n");} package2
		| /* to definiuje, ze moze nie istniec wogole 'package' */
		;
/* POKAZANIE IDENTIFIER:
w linijce ponizej wyswietlam wartosc zmiennej IDENTIFIER uzywajac w kodzie '$1'
te $1 przez 'bison' zostanie zastapione zmienna,
ktora zawiera wartosc ostatnio wczytanego IDENTIFIER'a
[wiecej o tym skad $1 czy $3 jest w wykladzie na edux]
*/
package2	: IDENTIFIER {printf("%s\n", $1);} package3
		;

package3	: DOT {printf(".\n");} package4
		| SEMICOLON {printf(";\n");} package5
		;

package4	: IDENTIFIER {printf("%s\n", $1);} package3
		;

package5	: {printf("\n[wczytano package]\n");};

/* import - wczytanie w petli 0 do nieskonczonosci */
/*
dla wlasnej wygody zaczalem numerowac od '0' te opcje ktore beda w petli [w zerze definiuje petle],
a od 1 te ktore moga wystapic tylko raz
*/
import0		: import0 import1
/*
regula powyzej tworzy petle:
'wczytaj import przed importem [import0] i jeden 'import' [import1]'
wczyta wszystkie import do poki jakies sa,
samo sie auto-magicznie kapnie kiedy sie skoncza importy i wyjdzie z petli
*/
		|
/* regula powyzej (pusta) definiuje, ze moze nie byc ani jednego import i 
za razem pozwala na skonczenie petli (!) */
		;

import1		: IMPORT {printf("import\n");} import2
		;

import2		: IDENTIFIER {printf("%s\n", $1);} import3
		;

import3		: DOT {printf(".\n");} import4
		| SEMICOLON {printf(";\n");} import6
		;

import4		: IDENTIFIER {printf("%s\n", $1);} import3
		| STAR {printf("*\n");} import5
		;

import5		: SEMICOLON {printf(";\n");} import6
		;
import6		: {printf("\n[wczytano import]\n");};

%%
/* ponizej juz tylko typowe formulki */
int yyerror(char *s)
{
	printf("skladnia wczytywanego kodu jest nie poprawna! [error: %s]\n",s);
}
int main(void)
{
	yyparse();
}

parser.lex (flex)

%{
	// zalaczamy plik wygenerowany przez bisona
	#include "parser.h"
%}
identifier	[_a-zA-Z]+[_a-zA-Z0-9]*
decimalNumber	[0-9]+
blanks		[ \t\n]+

%%

%{
/*
komentarze w flex trzeba umieszczac w takim czyms,
inaczej moze wyskoczyc error przy kompilacji
*/
%}

<INITIAL>"." return(DOT);
<INITIAL>"*" return(STAR);
<INITIAL>";" return(SEMICOLON);
%{
/*
po 'package' i 'import' powinna byc co najmniej jedna 'spacja/tab/nowa linia',
sprawdze to od razu w flex, zeby nie miec 100 razy w bisonie wczytywania tokena nowego 'BLANKS'
*/
%}
<INITIAL>"package"{blanks}+ return(PACKAGE);
<INITIAL>"import"{blanks}+ return(IMPORT);

<INITIAL>{identifier} {
%{
/*
magiczny kod do przekazania nazwy wczytanej z wejscia,
aby w bisonie znac nazwe zmiennej, a nie tylko fakt jej istnienia
(chce nie tylko znac skladnie, ale tez wyswietlic nazwy zmiennych)
*/
%}
	yylval.sval = malloc(strlen((char*)yytext));
	strncpy(yylval.sval, yytext, strlen((char*)yytext));
	return(IDENTIFIER);
}

<INITIAL>{decimalNumber} return(DECNUMBER);
<INITIAL>{blanks} { /* nic */ }

c.sh (kompilacja w 1 skrypcie)

bison -d parser.y
mv parser.tab.h parser.h
mv parser.tab.c parser.y.c
flex parser.lex
mv lex.yy.c parser.lex.c
gcc -g -c parser.lex.c -o parser.lex.o
gcc -g -c parser.y.c -o parser.y.o
gcc -g -o parser parser.lex.o parser.y.o -lfl

jak kompilować projekt (mając 3 powyższe pliki w jednym katalogu na linux):

sh c.sh

jak odpalić swój program przekazując mu na wejście zawartość pliku dane1.txt

./parser < dane1.txt

Może ktoś coś z tego ogarnie.

Na linux trzeba zainstalować (komenda dla ubuntu – wpisuje się w ‚Terminal’):
sudo apt-get install bison flex gcc

Na windows są podobno duże problemy, więc nie wiem czy warto marnować czas czy od razu zainstalować wirtualke (VMware Player) z linux (Ubuntu Desktop).

Opublikowano PJWSTK – AUG | Skomentuj

[AUG] Kolokwium z 2012 z rozwiązaniem

Rozwiązania są poprawne. Niektóre można jeszcze skrócić, ale to nie jest wymagane na kolokwium.

Strona 1:

 

1

 

Strona 2:

2

 

Strona 3:

3

 

(kliknij na obrazku, aby powiększyć)

Opublikowano PJWSTK – AUG | Skomentuj

[AUG] Praca domowa do wykładu 13 (na 16-17 maja)

Na jutro wykład nr 13 (według eduxa) – Automaty Stosowe

LUB NA JUTRO WYKŁAD NUMER 12 (ten z posta niżej), nie wiem jak to będzie liczone. Najlepiej się obu nauczyć 🙂

Mam tylko średnio czytelną notatkę z wykładu:
20140514_001(kliknij obrazek, aby powiększyć)

Opublikowano PJWSTK – AUG | Skomentuj

[AUG] Praca domowa do wykładu 12

Notatka z wykładu. Po // są komentarze, ICH NIE PISZEMY NA TABLICY!

// lex z przykladow do wykladu nr 12

// a teraz bizon:

// definicje
%{
include costam.h
%}
%token NUM
%% // teraz gramatyka
input : /* nic */
      | input expr "\n" {printf("\n");}; // daje printf ktore 'przywroci koniec linii'
expr  : expr '+' mult { printf("+");};
      | expr '-' mult { printf("-");};
	  | mult; // zejscie nizszego rzedu (??)
mult  : mult '*' term { printf("*");};
      | mult '/' term { printf("/");};
	  | term;
term  : NUM { printf("%d", $1);};
      | '(' expr ')';
%% // main
int main()
{
	yyparse();
	return 0;
}
Opublikowano PJWSTK – AUG | Skomentuj

[AUG] Praca domowa do wykładu 6

PRACA DOMOWA:

zad1aug zad2aug zad3aug

Opublikowano PJWSTK – AUG | Skomentuj

MAS – Mini projekt 2 – drugie pytania/problemy

Jak usuwać asocjacje wiele do wiele lub wiele do jeden? Pojawia się tu jeden banalny programistyczny problem. Nie można usuwać z listy/mapy po której się właśnie iteruje:

ŹLE:

public void usun() throws Exception
{
    for(Wyplata wyplata : wyplaty)
    {
        this.usunWyplate(wyplata);
    }
    wyplaty.clear();
    wszystkieWyplaty.clear();
}

DOBRZE:

@SuppressWarnings("unchecked")
public void usun() throws Exception
{
    for(Wyplata wyplata : (Vector<Wyplata>) wyplaty.clone())
    {
        this.usunWyplate(wyplata);
    }
    wyplaty.clear();
    wszystkieWyplaty.clear();
}

Jak widać w pierwszym przypadku próbuje usuwać elementy z Vector’a po którym iteruje. Nie ważne czy będzie to iteracja for(Klasa element : lista) czy for(int i = 0; i < lista.size(); i++) i tak problem będzie występował i usunie się tylko jeden/kilka elementów z listy lub wywali Exception.

Rozwiązaniem (DOBRY kod) jest zrobienie ‚płytkiej’ kopii listy funkcją clone() i iterowanie po niej.

Ewentualnie to też powinno się sprawdzić (nie testowałem):

while(lista.size() > 0)
{
	// usuwa pierwszy element jak dluga sa jakies elementy
	lista.remove(0);
// mozna tu tez dac 'lista.get(0)', cos z tym zrobic, a potem dopiero remove(0)
}
Opublikowano PJWSTK – MAS | Skomentuj

MAS – Mini projekt 2 – pierwsze pytanie

Dostałem pierwszy kod programu od kolegi i z wielu wymienionych błędów najbardziej rzuca się jeden który powtarza się w każdym projekcie który sprawdzam. W 2 klasach są funkcje do dodawania asocjacji. Wywołanie ‚jednej’ wywołuje ‚drugą’, ale wywołanie ‚drugiej’ nie wywołuje ‚pierwszej’.

Przez co w projekcie o np. Schronisku [świetny pomysł do wykorzystania jak nie macie żadnego) obiekt ‚Buda’ może wiedzieć jaki ‚pies’ powinien w niej siedzieć, ale ‚Pies’ nie wie, że ma ‚budę’.

Krótki przykład z kodem kolegi przed i po przeróbkach.
UWAGA: to jest kod w pseudokodzie (prawie w C#), ale w niczym się nie odpali, można się tylko wzorować na nim i poprawić samodzielnie błąd w swoim problemie

BAARDZO WAŻNE: w kodzie przykładowym poprawiam kod który przechowuje odniesienia jako ‚int’ z ID obiektu (które jest ‚gdzieś tam nadawane’ unikalne) i używam ‚restauracja.GetID()’, a nie referencji do obiektu (samo ‚restauracja’), bo w tym projekcie jest założenie, że dane będą przechowywane w bazie danych i muszą mieć unikalne ID, a w JAVIE której większość używa trzymamy dane w pliku (ObjectPlus za to odpowiada) i powinniśmy trzymać referencje, a nie ID jakieś przechowywane w każdym obiekcie – o to może się baaaardzo czepiać przy sprawdzaniu projektów.

Czyli używamy:
private ArrayList<Student> znajomiStudenci = new ArrayList<Student>();

a nie:
private ArrayList<Integer> idZnajomiStudenci = new ArrayList<Integer>();

Teraz przejdziemy wreszcie do przykładowego kodu:

 

public void KLIENT.DodajUlubionaRestauracje(Restauracja restauracja)
{
	// kompozycja!, zapamietujemy w Directory [HashMap w javie] jakis String unikalny i jakas wartosc/obiekt
	LubianeRestauracje.Add(restauracja.GetNazwa(), restauracja.GetID());
	// to jest ok, wywoluje metode w drugiej klasie
	restauracja.DodajKlienta(this); // this, nie this.GetID()
}

// przekazac trzeba obiekt (Klient klient), a nie 'id' samo (int id), bo chcemy na nim cos wywolac
public void RESTAURACJA.DodajKlienta(Klient klient)
{
	// tutaj lipa, nic nie wywolujemy w drugim obiekcie
	Klienci.Add(klient.GetID());
	/*
	Co z tego wynika?
	jesli jakis programista wywola:
	RESTAURACJA.DodajKlienta(klientStefan);
	to restauracja bedzie widziala, ze stefan ja lubi, ale stefan nie bedzie tego wiedzial
	*/
}

// KOD POPRAWIONY:

public void KLIENT.DodajUlubionaRestauracje(Restauracja restauracja)
{
	// dodajemy tylko jak nie mamy, dzieki temu unikniemy zapetlenia, ze funkcja X wywola Y, a Y wywola X i tak w kolko
	if(!LubianeRestauracje.Contains(restauracja.GetID()))
	{
		LubianeRestauracje.Add(restauracja.GetNazwa(),restauracja.GetID());
		// WAZNE, najpierw dodaje do swojej tablicy/listy, a potem wywoluje metode drugiego obiektu [inaczej zapetlenie]
		restauracja.DodajKlienta(this);
	}
}

public void RESTAURACJA.DodajKlienta(Klient klient)
{
	if(!Klienci.Contains(klient.GetID()))
	{
		Klienci.Add(klient.GetID());
		KLIENT.DodajUlubionaRestauracje(this);
	}
}

Opublikowano PJWSTK – MAS | Skomentuj

[AUG] Praca domowa do wykładu 4

Praca domowa

  1. (3p.) Podaj deterministyczny automat skończony akceptujący te słowa nad alfabetem $\{0, 1\}$, w których kazda seria zer i każda seria jedynek jest parzystej długości.
  2. (3p.) Podaj deterministyczny automat skończony akceptujący te słowa nad alfabetem $\{a,b\}$, które zawierają podsłowo $babbb$.
  3. (4p.) Podaj deterministyczny automat skończony akceptujący przecięcie języków akceptowanych przez automaty:
    \begin{displaymath}<br /> \begin{array}[t]{rc\vert cc}<br /> & & a & b \ \hline<br /> \to F & ...<br /> ... & b \ \hline<br /> \to & 1 & 2 & 1\\<br /> F & 2 & 1 & 2<br /> \end{array} \end{displaymath}

Odp. 1:

automat1

Odp. 2:

automat2

Odp. 3:

Treść zadania + odpowiedź:

automat3img

Co gdzie się ‚przenosi’:

automat3_kolorwy

Opublikowano PJWSTK – AUG | Skomentuj

[MAS] Mini projekt 1

Mój projekt pierwszy z baaardzo obszernym komentarzem.

Krótka instrukcja użycia:

mas_mp1

Wymagania co do projektu są tu:
http://www.users.pjwstk.edu.pl/~mtrzaska/Files/MAS/MAS-informacje-stacjonarne.pdf

Jak zrobić ‚ekstensje’ (są w projekcie, ale tu macie opis o co chodzi):

http://www.mtrzaska.com/plik/mas/mas-wyklad-nr-04

Projekt składa się z 4 plików:

Main.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
import java.util.Random;


public class Main
{
	public static void main(String[] arg) throws Exception
	{
		// jesli wczesniej cos zapisalem [odpalam program po raz kolejny] to wczytaj to co bylo
		// DEMONSTRACJA DZIALANIA 'TRWALYCH EKSTENSJI' (trwale czyli nie znikaja po zamnieciu programu)
		if(new File("mojeTajneDane").isFile())
		{
			try
			{
				// plik jest w 'workspace'
				FileInputStream fileIn = new FileInputStream("mojeTajneDane");
				ObjectInputStream inStream = new ObjectInputStream(fileIn);
				// odczytuje wszystko z dysku do pliku 'mojeTajneDane' jedna linijka
				// 'magia javy' zrobi reszte
				ObjectPlus.odczytajEkstensje(inStream);
				inStream.close();
				fileIn.close();
			}
			catch(IOException i)
			{
				i.printStackTrace();
				return;
			}
			catch(ClassNotFoundException c)
			{
				System.out.println("Klasa nie znaleziona.");
				c.printStackTrace();
				return;
			}
		}
		
		
		
		// utworz nowego Grzegorza o wzroscie miedzy 165, a 195
		Random rand = new Random();
		Student studencik = new Student("Grzegorz" + rand.nextInt(100), 165 + (rand.nextInt(31)));
		// na date urodzenia ustawiamy czas jaki jest 'teraz'
		studencik.ustawDateUrodzenia(new Date());
		// wywoluje przeciazana metode z parametrem 'int'
		studencik.dodajOcene(2 + rand.nextInt(4));
		// wywoluje przeciazana metode z parametrem 'Double'
		studencik.dodajOcene(new Double(2 + ((double)rand.nextInt(7) / 2)));
		// pokaz wszystkich Grzegorzy jacy istnieja
		ObjectPlus.pokazEkstensje(Student.class);
		
		
		
		// przed zamknieciem programu zapisz wszystkie ekstensje do pliku
		// DEMONSTRACJA DZIALANIA 'TRWALYCH EKSTENSJI' (trwale czyli nie znikaja po zamnieciu programu)
		try
		{
			// plik jest w 'workspace'
			FileOutputStream fileOut = new FileOutputStream("mojeTajneDane");
			ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
			// zapisuje wszystko na dysk do pliku 'mojeTajneDane' jedna linijka
			// 'magia javy' zrobi reszte
			ObjectPlus.zapiszEkstensje(outStream);
			outStream.close();
			fileOut.close();
		}
		catch(IOException i)
		{
			i.printStackTrace();
		}
		
	}
}

Osoba.java

import java.util.Date;


public abstract class Osoba extends ObjectPlus
{
	/*
	wymagane do serializacji, w przyszlosci jak cos zmienisz w tej klasie [dodasz/usuniesz atrybut]
	to zmienisz ta liczbe na inna, dzieki temu mechanizm 'serialize' nie pozwoli zaladowac 
	pliku z dysku z starymi danymi do programu ktory uzywa innej klasy
	(przeciez moze byc zupelnie inna klasa o nazwie Student i dane takie jak 'oceny' moga w niej
	nie wystepowac)
	 */
	private static final long serialVersionUID = 1L;
	/* PRZYPOMNIENIE: Co to jest 'protected'?
	 * To takie cos jak 'private' tylko, ze zmienna jest widziana w klasach 'dziedziczacych' (rozszerzajacych).
	 * Dzieki temu bedzie mozna wyswietlac np. 'imie' w studencie ktory dziedziczy po osobie.
	 */
	
	// atrybut prosty, wymagany, pojedynczy, obiektu
	protected String imie;
	/*
	 * WYMAGANY:
	 * zawsze kiedy go ustawiamy to sprawdzamy czy ktos nam nie przekazal 'null'
	 */
	
	// atrybut prosty, opcjonalny, pojedynczy, obiektu
	protected String nazwisko;
	/*
	 * OPCJONALNY:
	 * zawsze kiedy go wyswietlany to sprawdzany cyz ktos nam nie przekazal 'null'
	 * jesli 'null' to trzeba wyswietlic o tym informacje lub inaczej to 'obsluzyc',
	 * bo proba wyswietlenie 'null' skonczy sie bledem programu
	 */
	
	// atrybut zlozony, opcjonalny, pojedynczy, obiektu
	protected Date dataUrodzenia;
	/*
	 * ZLOZONY:
	 * to taki ktory zawiera w sobie wiecej niz jedna informacje
	 * ogolnie chodzi o odniesienie sie do innego obiektu (oprocz 'String')
	 * 
	 */
	// atrybut prosty, wymagany, pojedynczy, obiektu
	protected int wzrost = 0;
	/*
	 * jest tu tylko po to, zeby wyliczac srednia (i miec cos 'pochodnego')
	 */
	
	// atrybut prosty, pojedynczy, wyliczalny (pochodny), klasowy
	private static double sredniWzrost = 0;
	/*
	 * KLASOWY:
	 * dotyczy klasy, czyli wszystkich 'Osob', a nie jednej konkretnej
	 * technicznie: zmienna typu static
	 * 
	 * POCHODNY:
	 * mozna go wyliczyc, w tym wypadku wystarczylo by pobrac wszystkie Osoby z 'ekstensji' ObjectPlus
	 * pobrac ich wzrost i wyliczyc srednia, ale prosciej to po prostu pamietac
	 * i liczyc tylko raz przy dodawaniu osoby
	 */
	// atrybut prosty, pojedynczy, klasowy - potrzebny do liczenia sredniej
	private static int iloscOsob = 0;
	
	// konstruktor nie jest 'pusty', bo imieOsoby jest 'wymagane', wiec musi byc w kazdym konstruktorze
	Osoba(String imieOsoby, int wzrostOsoby)
	{
		/*
		 * BARDZO WAZNE: kazdy konstruktor klasy dziedziczacej po klasie ObjectPlus musi wywolywac 'super()'
		 * Co to jest 'super()'?
		 * Jest to cos co odpali konstruktor w klasie 'wyzej' / 'u rodzica' czyli w ObjectPlus.
		 * A co to robi?
		 * To zapewnia, ze kazdy utworzony obiekt jest na liscie 'ekstensji' w ObjectPlus.
		 * Konstruktor w ObjectPlus zajmuje sie dodawaniem/tworzeniem list ekstensji.
		 */
		super();

		
		
		// tutaj dbamy, aby wymagany atrybut byl ustawiony, a nie wskazywal na 'null'
		if(imieOsoby == null)
		{
			throw new NullPointerException("Osoba musi miec imie");
		}
		this.imie = imieOsoby;
		
		// 'int' nie moze byc 'nullem', wiec tego nie sprawdzamy
		// ale wymagamy podania tego w konstruktorze, wiec kazda osoba bedzie miala wpisany wzrost
		this.wzrost = wzrostOsoby;
		
		
		
		// to nam sie przyda do liczenia sredniej
		iloscOsob++;
		// a tu troche Drabikologi i mamy srednia
		sredniWzrost += (this.wzrost - sredniWzrost) / iloscOsob;
	}

	/*
	 * PRZESLANIANIE METOD:
	 * w nadklasie Osoba metoda ta zwraca tylko imie,
	 * a w Student imie z dodanym na poczatku tekstem 'Student'
	 * jaki tego sens? trudno mi wymyslic jakas sensowna przeslaniana funkcje
	 * 
	 * technicznie: w klasie dziedziczacej jest metoda o takiej samej nazwie, takich samych argumentach,
	 * ale zwraca cos innego
	 */
	public String getImie()
	{
		return this.imie;
	}
	
	/*
	 * METODA KLASOWA:
	 * metoda operujaca na zmiennych klasowych, a nie obiekcie
	 * technicznie: typu static
	 */
	public static double getSredniWzrost()
	{
		return sredniWzrost;
	}

	/*
	 * demonstracja roznicy w poslugiwaniu sie atrybutami 'wymaganymi' i 'opcjonalnymi'
	 */
	public void ustawImie(String imie)
	{
		if(imie == null) // uwaga wymagany!
		{
			throw new NullPointerException("Osoba musi miec imie");
		}
		this.imie = imie;
	}
	
	public void ustawNazwisko(String nazwisko)
	{
		this.nazwisko = nazwisko;
	}
	
	public void ustawDateUrodzenia(Date dataUrodzenia)
	{
		this.dataUrodzenia = dataUrodzenia;
	}
	
	public String toString()
	{
		String ret = new String();
		ret += "Imie: " + getImie();
		ret += "\nNazwisko: ";
		if(nazwisko != null) // uwaga opcjonalny!
			ret += nazwisko;
		else
			ret += "bez nazwiska";

		ret += "\nWzrost: " + wzrost;

		ret += "\nData urodzenia: ";
		if(dataUrodzenia != null) // uwaga opcjonalny!
			ret += dataUrodzenia;
		else
			ret += "nie znana";
		return ret;
	}
}

Student.java

import java.util.Vector;


public class Student extends Osoba
{
	/*
	wymagane do serializacji, w przyszlosci jak cos zmienisz w tej klasie [dodasz/usuniesz atrybut]
	to zmienisz ta liczbe na inna, dzieki temu mechanizm 'serialize' nie pozwoli zaladowac 
	pliku z dysku z starymi danymi do programu ktory uzywa innej klasy
	(przeciez moze byc zupelnie inna klasa o nazwie Student i dane takie jak 'oceny' moga w niej
	nie wystepowac)
	 */
	private static final long serialVersionUID = 1L;
	
	// atrybut prosty, powtarzalny, obiektu
	private Vector<Double> oceny = new Vector<Double>();
	/*
	 * POWTARZALNY:
	 * obiekt zawiera 0 lub wiecej takich 'elementow'
	 * technicznie: lista/tablica
	 */
	
	Student(String imieOsoby, int wzrostOsoby)
	{
		/*
		 * 'super', bo dziedziczy po klasie ktora dziedziczy po ObjectPlus
		 * z parametrem 'imieOsoby' i 'wzrostOsoby', bo takie atrybuty sa wymagana w Osoba
		 */
		super(imieOsoby, wzrostOsoby);
	}
	
	/*
	 * PRZESLANIANIE METOD:
	 * w nadklasie Osoba metoda ta zwraca tylko imie,
	 * a w Student imie z dodanym na poczatku tekstem 'Student'
	 * jaki tego sens? trudno mi wymyslic jakas sensowna przeslaniana funkcje
	 * 
	 * technicznie: w klasie dziedziczacej jest metoda o takiej samej nazwie, takich samych argumentach,
	 * ale zwraca cos innego
	 */
	public String getImie()
	{
		return "Student " + this.imie;
	}
	
	/*
	 * PRZECIAZANIE METOD:
	 * metody maja taka sama nazwe, ale przyjmuja rozne parametry
	 * w tym przypadku jedna 'Double', a druga 'int'
	 */
	public void dodajOcene(Double ocena) throws Exception
	{
		if(ocena == null || ocena < 2 || ocena > 5)
		{
			throw new Exception("Ocena musi byc pomiedzy 2, a 5");
		}
		oceny.add(ocena);
	}
	public void dodajOcene(int ocena) throws Exception
	{
		if(ocena < 2 || ocena > 5)
		{
			throw new Exception("Ocena musi byc pomiedzy 2, a 5");
		}
		oceny.add(new Double(ocena));
	}
	
	public String toString()
	{
		// na poczatek opisu studenta wklejamy opis z Osoby (imie, nazwisko..) wywolujac metode z klasy 
		// z ktorej dziedziczymy, robimy to uzywajac 'super'
		String ret = super.toString();
		ret += "\nOceny: ";
		if(oceny.size() > 0)
		{
			for(Double ocena : oceny)
			{
				ret += ocena + ",";
			}
		}
		else
		{
			ret += "brak ocen";
		}
		return ret;
	}
}

ObjectPlus.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Hashtable;
import java.util.Vector;

/* 
 * To jest klasa z wykladu nr 4 z drobnymi zmianami, zeby eclipse nie wywalal 'ostrzezen'
 * --------------------
 * klasa zrobina przez wykladowce!, wiec raczej nie powinien sie czepiac
 * ale trzeba rozumiec KAZDY szczegol jej dzialania!
 * */
public class ObjectPlus implements Serializable
{
	/*
	wymagane do serializacji, w przyszlosci jak cos zmienisz w tej klasie [dodasz/usuniesz atrybut]
	to zmienisz ta liczbe na inna, dzieki temu mechanizm 'serialize' nie pozwoli zaladowac 
	pliku z dysku z starymi danymi do programu ktory uzywa innej klasy
	(przeciez moze byc zupelnie inna klasa o nazwie Student i dane takie jak 'oceny' moga w niej
	nie wystepowac)
	 */
	private static final long serialVersionUID = 1L;
	/*
	(w tym tlumaczeniu bede uzywal slowa 'tablica' zamiast 'lista', roznica? lista [z ktorej korzystamy pod nazwa Hashtable!]
	sama 'rosnie' jak do niej dodajemy obiekty, a tablice maja staly rozmiar np. 'new Integer[5]' - 5 elementow)
	
	Tlumaczenie typow:
	1. Class<? extends ObjectPlus> - obiekt typu Class pobrany z obiektu ktory rozszerza ObjectPlus, czyli np. Osoba lub Student,
	String czy Integer nie rozszerzaja ObjectPlus, wiec nie zostana zaakceptowane
	2. Vector<ObjectPlus> - lista/kontener obiektow typu ObjectPlus, do takiej listy mozna wsadzic dowolny obiekt
	ktory rozszerza ta klase, czyli np. Student czy Osoba
	
	Opis:
	To jest 'tablica tablic', a dokladniej tablica ktora jako klucz nie ma liczby, a.. KLASE (Class)!
	Class to o dziwo w Javie klasa ktora przechowuje informacje o klasie, mozna pobrac obiekt typu Class z kazdego obiektu
	w Javie uzywajac:
	Class klasaObiektu = mojObiekt.getClass();
	No wiec mamy juz tablice ktora uzywa jako klucza Class, a jakie dane przechowuje? Przechowuje Vector<ObjectPlus>,
	czyli tablice obiektow typu ObjectPlus:
	1. Osoba rozszerza ObjectPlus [extends], wiec tez moga ja wrzucic do tej tablicy
	2. Student rozszerza Osoba ktora rozszerza ObjectPlus, wiec tez moge ja tam wrzucic
	
	A po co mi wogole tablica tablic zamiast zwyklej tablicy?
	Bo ObjectPlus w projekcie docelowym moze byc rozszerzany przez wiele obiektow roznych
	klas jak np. 'Wplata', 'Ocena', 'Przedmiot' itd., a nie chce mi sie pisac nowego ObjectPlus dla kazdej z nich
	Nie chce tez przechowywac wszystkich obiektow w jednej tablicy [typu Object, wtedy moge tam wrzucic wszystko],
	bo wtedy 'pobranie wszystkich 'Student' wymagalo by przegladania wszystkich elementow tablicy i
	sprawdzania ktorzy to Studenci.
	 */
	private static Hashtable<Class<? extends ObjectPlus>, Vector<ObjectPlus>> ekstensje = new Hashtable<Class<? extends ObjectPlus>, Vector<ObjectPlus>>();

	/**
	 * Konstruktor.
	 */
	public ObjectPlus()
	{
		Vector<ObjectPlus> ekstensja = null;
		Class<? extends ObjectPlus> klasa = this.getClass();

		if(ekstensje.containsKey(klasa))
		{
			// Ekstensja tej klasy istnieje w kolekcji ekstensji
			// jest juz jakis np. Student, wiec jest i lista studentow, nie chce tworzyc nowej listy,
			// tylko dodac nowego studenta do listy juz istniejacej
			ekstensja = ekstensje.get(klasa);
		}
		else
		{
			// Ekstensji tej klasy jeszcze nie ma -> dodaj ją
			// to wystepuje kiedy pierwszy raz dodajemy obiekt danego typu (np. Student) do ekstensji
			ekstensja = new Vector<ObjectPlus>();
			ekstensje.put(klasa, ekstensja);
		}
		// a tu wreszcie dodaje studenta do listy nowej LUB istniejacej
		ekstensja.add(this);
	}
	
	/**
	 * Zapisuje wszystkie ekstensje do podanego strumienia (wersja z serializacja).
	 * Metoda klasowa.
	 * @throws IOException 
	 */
	public static void zapiszEkstensje(ObjectOutputStream stream) throws IOException
	{
		/*
		'magia javy' zamienia obiekt (Hashmape) zawierajacy inne obiekty w tekst,
		wiec jak zawiera liste Studentow to Ci studenci maja np. atrybut 'Date dataUrodzenia' i to tez sie zapisze
		(Date jest 'serializable' jak wiekszosc klas uzywanych na codzien w javie)
		(wszystkie obiekty jakie zawiera ekstensja musza rozszerzac interfejs 'Serializable')
		java znajdzie wszystkie powiazane obiekty z tymi obiektami ktore mamy w hashmap 'ekstensje' i 
		wszystkie powiazane z ich powiazaniami itd. i wszystko zapisze jako tekst!
		a potem jeszcze moze z tego tekstu odtworzyc ten obiekt [i obiekty powiazane], magia!
		
		UWAGA: to zapisze tylko zmienne 'obiektu', zmienne 'klasowe' (te z 'static') nie zostana zapisane i
		to jeden z problemow z takim prostym zapisem, ale mozna samemu dopisac zapis 'static'
		na szczescie to nie jest wymagane w MP_1, a jedynie w projekcie semestralnym
		*/
		stream.writeObject(ekstensje);
	}

	/**
	 * Odczytuje wszystkie ekstensje z podanego strumienia (wersja z serializacja).
	 * Metoda klasowa.
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 */
	@SuppressWarnings("unchecked")
	public static void odczytajEkstensje(ObjectInputStream stream) throws IOException, ClassNotFoundException
	{
		/*
		tutaj 'magia javy' odtwarza dane zapisane jako tekst do pliku (zapisane w funkcji wyzej)
		 */
		ekstensje = (Hashtable<Class<? extends ObjectPlus>, Vector<ObjectPlus>>) stream.readObject();
	}	
	
	/**
	 * Wyswietla ekstensje.
	 * Metoda klasowa.
	 * @throws Exception 
	 */
	public static void pokazEkstensje(Class<? extends ObjectPlus> klasa) throws Exception
	{
		/*
		wystarczy gdzies w programie wywolac ta funkcje tak:
		ObjectPlus.pokazEkstensje(Student.class);
		aby wyswietlic wszystkie obiekty typu 'Student' istniejace w programie
		 */
		Vector<ObjectPlus> ekstensja = null;
		
		if(ekstensje.containsKey(klasa))
		{
			// Ekstensja tej klasy istnieje w kolekcji ekstensji
			ekstensja = ekstensje.get(klasa);
		}
		else
		{
			throw new Exception("Unknown class " + klasa);
		}
		
		System.out.println("Ekstensja klasy: " + klasa.getSimpleName());

		for(Object obiekt : ekstensja)
		{
			System.out.println(obiekt + "\n");
		}
	}
	
}

Mam nadzieję, że będziecie przestrzegać instrukcji.

Wszystko w .zip:

MAS_MP1_Jerzego

Opublikowano PJWSTK – MAS | Otagowano , , | Skomentuj

[AUG] Praca domowa do wykładu 2

Rozwiązania 5 przykładów z zadania nr 1 z opisami:

1.15.
b*(a(bb)*)*
[nic, same ‚b’, zaczyna sie na (‚a’ lub ‚b’) i po kazdym ‚a’ parzysta liczba ‚b’]
1.16.
(aa*(b(bb)*))*a* | ((b(bb)*)aa*)* | (b(bb)*)
[nic, same ‚a’, zaczyna sie na ‚a’ i konczy (na ‚b’ lub na ‚a’)] | [zaczyna sie na ‚b’ i konczy na ‚a’] | [zaczyna sie na ‚b’ i konczy na ‚b’]
1.17.
((a(aa)*) | (b(bb)*))* – nie jestem pewien czy to nie pusci parzystych
1.18.
(a*aabaaa*)*a*
[nic, same ‚a’ lub do woli ‚a’, ale conajmniej 2, potem ‚b’ i do woli ‚a’, ale conajmniej 2]
lub:
(aabaa | a)*
[nic, same ‚a’ lub do woli ‚a’, ale conajmniej 2 przed i po ‚b’, a potem do woli ‚a’]
1.19.
b* | b*a(bbba)*b*
[nic, same ‚b’] | [zaczyna sie od ‚b’ lub jednego ‚a’, potem przed kazdym ‚a’ jest ‚bbb’, a potem do woli ‚b’]

Opublikowano PJWSTK | Skomentuj