Lab Wpółbieżny i obiektowy zadanie 2

Drugie zadanie z labu współbieżnego i obiektowego wygląda tak:


Napisz program kalkulator, który pozwala wczytywać wyrażenia arytmetyczne ze zmiennymi i wyliczać ich wartości. Wyrażenia mogą być dowolnie rozbudowane, choć składają się tylko z czterech podstawowych działań arytmetycznych. Zmienne i wyrażenia są typu całkowitego. Nazwy zmiennych składają się tylko z liter. Dane użytkownik podaje ze standardowego wejścia. Wyrażenia postaci % oznaczają odwołanie do wyrażenia wcześniej zdefiniowanego (jeśli numer jest = bieżącemu numerowi takie wyrażenie jest błędne, należy wypisać użytkownikowi komunikat o błędzie,
tak samo jak w przypadku dzielenia przez 0).

Przykład konwersacji z programem (liczby na początku wierszy i znak ">" wyświetla sam program, tekst pogrubiony pochodzi od użytkownika):

1>x=9
2>x = -3
3>y=4
4>x+y*2/3
x+y*2/3 = -1
5>zz+zz
zz+zz = NIEOZNACZONE
6>%5+%5
(zz+zz)+(zz+zz) = NIEOZNACZONE
7>%6/%6
((zz+zz)+(zz+zz))/((zz+zz)+(zz+zz)) = NIEOZNACZONE
8>zz=1
9>%7
((zz+zz)+(zz+zz))/((zz+zz)+(zz+zz)) = 1
10>x=0
11>%4
x+y*2/3 = 2
12>1/x
1/x = BŁĄD
13>zz=5
14>zz
zz=5
15>%8
zz=5
16>
Koniec działania programu.

Jakich wzorców projektowych użyjesz w swoim rozwiązaniu?

A oto rozwiązanie:
Rany! Ale to zadanie było męczące!
Kalkulator

Lab HTML i JAVA, zadanie 4

Trzecie zadanie z nowego przedmiotu, Laboratorium HTML i Java brzmiało następująco:

Napisz aplet, który zdefiniuje własną obsługę kliknięć myszy i w reakcji na każde z nich będzie rysował na ekranie wielokąt o bokach wyznaczonych przez punkty kliknięcia. Możesz skorzystać z klasy Polygon.

A oto rozwiązanie:
Zadanie 4

Struktury Danych

Ze struktur danych dostaliśmy wyobraźcie sobie do napisania program! Kto by pomyślał?

Oto treść:

Motel
Dost˛epna pami˛e´ c: 64MB.
Profesor Makary wybiera si˛e na zimowy urlop na narty. Poniewa˙ z droga z domu profesora do górskiego kurortu jest daleka,
profesor liczy si˛e z konieczno´ sci ˛a podzielenia jej na dwa dzienne etapy, z noclegiem w przydro˙ znym motelu. Podró˙ ze go m˛ecz ˛a,
wi˛ec tras˛e i miejsce na nocleg chce wybra´ c tak, ˙ zeby oba fragmenty drogi nie były zbyt długie. Dokładniej, chciałby, aby dłu˙ zszy
z dwóch dziennych etapów był mo˙ zliwie najkrótszy.
Pomó˙ z profesorowi zaplanowa´ c tras˛e dojazdu, pisz ˛ac program, który obliczy najmniejsz ˛a mo˙ zliw ˛a długo´ s´ c dłu˙ zszego etapu.
UWAGA: Mo˙ ze si˛e zdarzy´ c, ˙ ze w optymalnym rozwi ˛azaniu który´ s z etapów ma długo´ s´ c 0 (czyli w rzeczywisto´ sci cała trasa
zostanie przebyta w jednym etapie).
Wej´ scie
W pierwszym wierszu znajduj ˛a si˛e dwie liczby całkowite n i m (2 ? n ? 50000, 1 ? m ? 1000000). Pierwsza z nich oznacza
liczb˛e punktów stanowi ˛acych potencjalne miejsca postoju, ponumerowanych od 0 do n?1 (punkt numer 0 to dom profesora,
punkt n?1 to kurort, a pozostałe to motele). Druga to liczba odcinków dróg ł ˛acz ˛acych punkty. Ka˙ zdy z kolejnych m wierszy
zawiera trzy liczby całkowite a, b, c, gdzie 0?a,b<n, a 6=b, 0?c?10000. Liczby a i b oznaczaj ˛a punkty na drogach, za´ s c to
długo´ s´ c odcinka drogi prowadz ˛acego bezpo´ srednio od a do b. (UWAGA: długo´ sci odcinków dróg od a do b i od b do a nie musz ˛a
by´ c równe; w szczególno´ sci który´ s z nich mo˙ ze wcale nie istnie´ c). Liczby w ka˙ zdym wierszu s ˛a pooddzielane pojedynczymi
spacjami.
Wyj´ scie
W jedynym wierszu standardowego wyj´ scia nale˙ zy wypisa´ c najmniejsz ˛a mo˙ zliw ˛a długo´ s´ c dłu˙ zszego z dwóch etapów drogi z
domu profesora do kurortu.
Przykład
Dla danych wej´ sciowych:
4 5
0 1 1
0 2 4
1 2 2
1 3 4
2 3 3
poprawnym wynikiem jest:
3
Wyja´ snienie do przykładu. Optymalna trasa to: 0?1?2 (I etap); 2?3 (II etap)

A oto rozwiązanie:
Jakoś działa, z większy naciskiem na JAKOŚ niż na DZIAŁA
Zadanie

Lab HTML i JAVA zadanie 3

Trzecie zadanie z nowego przedmiotu, Laboratorium HTML i Java brzmiało następująco:

Napisz w Javie program do analizy utworów literackich mistrzów pióra.

Program ma wczytać ze standardowego wejścia plik tekstowy (w zamyśle utwór jednego z wieszczów, na przykład pobrany z internetu), policzyć częstości występowania w nim poszczególnych słów i wypisać na standardowe wyjście n najczęściej występujących wyrazów wraz z liczbą wystąpień każdego z nich. Liczbę n należy pobrać z wiersza poleceń. Program wypisując słowo powinien podać jego formę (chodzi o użycie wielkich i małych liter, a nie o formę gramatyczną) najczęściej występującą w tekście.

Ponadto w kodzie źródłowym programu, w pliku z główną klasą należy zamieścić komentarz podający dla n=8 wynik działania programu dla tekstu "Pana Tadeusza" (tekst ten jest zamieszczony w Moodle'u).

Uwagi:

    * Każde słowo należy wypisać w osobnym wierszu.
    * Po każdym wypisanym słowie należy po spacji podać liczbę jego wystąpień.
    * Słowa należy wypisać wg malejącej kolejności wystąpień w tekście (czyli jako pierwsze słowo należy podać to, które występuje najczęściej).
    * Jeśli kilka słów ma tę samą częstość wystąpień, to ich wzajemna kolejność wypisywania jest obojętna.
    * Jeśli jakiś utwór zawierałby mniej niż n różnych słów, to należy wypisać tyle słów, ile w utworze znaleziono.
    * Przy liczeniu liczb wystąpień słów należy utożsamiać małe i wielkie litery (tzn. w tekście "Ale, ale, ale!" uznajemy, że słowo "ale" wystąpiło 3 razy).
    * Przy wypisywaniu słów należy podać najczęściej występującą w tekście ich formę (tzn. dla tekstu "Ale, ale, ale!" należy wypisać postać "ale". Jeśli kilka postaci słowa występujących najczęściej ma jednakową liczbę wystąpień, można wybrać dowolną z nich (tzn. dla tekstu "Ale, ale!" można wypisać albo "Ale" albo "ale").
    * Należy uwzględniać polskie litery (tzn. w napisie "Liście" jest jedno słowo składające się z sześciu znaków).

Wskazówki:

    * Należy skorzystać z kolekcji.
    * Należy używać kolekcji uogólnionych (generic), a nie surowych (raw).
    * Do odczytywanie słów wygodnie użyć klasy Scanner. Do pobierania samych słów (tzn. bez kropek, przecinków itp.) z polskimi literami można użyć operacji
         skaner.useDelimiter("[^a-zA-ZąćęłńóśźżĄĆĘŁŃÓŚŹŻ]+");

A oto rozwiązanie:
Zadanie 3

Lab obiektowy i współbieżny zadanie 1

Pierwsze zadanie z fascynującego przedmiotu “Laboratorium Programowania Obiektowego i współbieżnego brzmi tak:”

Napisz w Javie hierarchię klas opisujących pracowników pewnej firmy komputerowej. Wyraź w tej hierarchii następujące fakty:

    *

      wszyscy pracownicy są ludźmi,
    *

      każdy kierownik projektu, projektant, analityk, tester, programista, a nawet sam prezes jest pracownikiem,
    *

      każdy kierownik projektu oraz prezes jest kierownikiem.


Tak zaprojektuj klasy by:

    *

      każdy człowiek znał swoje imię i nazwisko,
    *

      każdy pracownik znał swoje stanowisko (tekst) i swego szefa (oczywiście prezes nie ma szefa, szefem kierownika projektu jest prezes, szefami pozostałych pracowników są kierownicy projektów),
    *

      każdy pracownik, prócz prezesa, brał udział w dokładnie jednym projekcie, i oczywiście znał ten projekt,
    *

      każdy kierownik projektu znał członków swojego projektu,
    *

      każdy projektant znał swoją dziedzinę,
    *

      prezes był tylko jeden.


Stwórz też klasy opisujące:

    *

      projekt (zna swoją nazwę),
    *

      dziedzinę (wyznaczającą zakres kompetencji projektanta), dziedzina zna swój słowny opis.

Każdy z ludzi musi umieć podać swój opis tekstowy (komunikat toString). Opis ma zawierać wszystkie informacje, które zna dany człowiek (np. nazwę projektu, czy pełny opis szefa). Napisz fragment programu w Javie, który utworzy kilka (ok. 10) obiektów reprezentujących ludzi zatrudnionych w przykładowej firmie na różnych stanowiskach, umieści ich w kolekcji, a następnie wypisze opis każdego z nich. Zadbaj o to, by tworzenie nowych obiektów było jak najprostsze. Całość zaprojektuj w postaci pakietu i zapisz jako jeden plik jar (tu mogą się przydać informacje z przedmiotu HTML i Java).


Wskazówki:

    *

      przy implementacji prezesa posłuż się statyczną metodą produkującą, w celu zrealizowania wzorca Singleton,
    *

      rozwiązanie ma obrazować statyczny stan firmy, nie interesują nas zmiany (dynamiczne aspekty stanu firmy, np. to że ktoś awansuje),
    *

      zadanie jest proste.



A oto rozwiązanie:
Zadanie 1

Lab HTMLa i Javy, zadanie 2

Drugie zadanie z nowego przedmiotu, Laboratorium HTML i Java brzmiało następująco:

  Napisz klasę implementującą zbiór liczb całkowitych. Przy tworzeniu obiektów tej klasy, użytkownik podaje z jakiego zakresu liczb będą elementy tego zbioru (dla uproszczenia zakładamy, że to przedział o dolnej granicy 0) oraz ile wynosi maksymalna liczba elementów w zbiorze. Zbiór powinien mieć typowe operacje:

    * dodaj element,
    * usuń element,
    * podaj rozmiar,
    * sprawdź czy zadana liczba należy do zbioru,
    * podaj napis będący tekstową reprezentacją zbioru (toString).

W swojej implementacji zbioru:

    * użyj tablic,
    * sygnalizuj zgłoszeniem wyjątku przekroczenie maksymalnej liczności zbioru,
    * użyj statycznej metody produkującej, by na podstawie parametrów dostarczyć właściwą implementację zbioru (wektor charakterystyczny albo posortowana tablica).

A oto rozwiązanie:
Lab HTML i Java zadanie 2

Poster

Na wspaniałym moim kierunku Psychologia przeprowadzaliśmy replikę badania eksperymentalnego “Klipce” Lewickiego. Jak możecie poczytać w każdym podręczniku Psychologii, jest to eksperyment z zakresu tworzenia Pojęć. Temat ciekawy jak stan amerykańskich firm motoryzacyjnych.

Gdy już popełniliśmy owo badanie, nastąpiła sesja posterowa z udziałem gwiazd i celebrities Akademii Pedagogiki Specjalnej. Na owej sesji posterowej prezentowaliśmy swój plakat dotyczący wyżej wymienionego badania:

Lab HTMLa i Javy, zadanie 1

Pierwsze zadanie z nowego przedmiotu, Laboratorium HTML i Java brzmiało następująco:

Stwórz zestaw powiązanych stron (co najmniej 3, nie muszą być duże) dotyczących Twojego hobby. Strony te powinny spełniać następujące warunki: 
    * strony mają być stworzone ręcznie (tzn. nie powinny być wynikiem zapisania dokumentu Write'a czy Worda w formacie (X)HTML),
    * strony mają używać wspólnego arkusza stylów,
    * strony powinny być zapisane za pomocą kodowania utf-8 (żeby to można było zauważyć, strony powinny być po polsku),
    * wszystkie strony muszą być zapisane w tym samym standardzie (X)HTMLa,
    * wszelkie formatowania powinny być wyrażone za pomocą arkuszy stylów,
    * należy zdefiniować (i użyć) co najmniej jedną, własną klasę stylów, choćby do wyświetlenia tekstu z boku, jak to opisano w materiałach pomocniczych poniżej,
    * strony powinny zawierać co najmniej następujące elementy html:
          o a,
          o ul i ol,
          o dl (lista definicji, elementy zaznacza się znacznikami dt i dl),
          o table (tablica nie musi być duża, wystarczy nawet 2*2, byleby użyć zarówno th jak i td),
          o img,
          o h1.

Arkusz(e) stylów powinien zawierać co najmniej:

    * definicje własnej klasy (własnych klas),
    * selektor powodujący, że elemeny (li) z listy uporządkowanej (ol) będą wypisywane inną czcionką (np. innego rozmiaru czy koloru), niż elementy z listy nieuporządkowanej (ul),
    * formatowanie ekranowe i do druku: na wydruku wszystkie teksty mają być czarne (a na ekranie co najmniej część nie), ponadto na wydruku nie powinny się pojawić żadne rysunki/zdjęcia.
    * wszystkie strony i arkusze muszą walidować się narzędziem z witryny w3.org.

Nie wiedziałem, jak sobie poradzę ze zrobieniem STRONY INTERNETOWEJ ale musiłem stawić czoło temu zadaniu.

A oto rozwiązanie:
Lab HTML i JAVA 1

Eksperyment!

Zachęcająć nas perspektywą zaliczenia ćwiczeń, szanowne grono pedagogiczne na psychologii zadało nam następującą pracę:

  1. Sporządzić projekt badań własnych
  2. Sporządzić z owego projektu prezentację, która wszem i wobec wyjaśni o co chodzi.

Prezentacja wykonana w składzie:

  • Dorota Powęzka
  • Mateusz Bala
  • Anna Gutowska
  • Marta Koziarska
  • Sonia Kondej
  • Aleksandra Sawczuk
  • I, niżej podpisany – Artur Piszek

Oto filmik wstępny, wyjaśniający o co kaman:

Oto sama prezentacja:

Do zobaczenia TU

I jeszcze filmik ze środka:

Laboratorium C++

Zadanie z laboratorium programowania C++ na Informatyce UW.

Program zaliczeniowy ? wersja finalna ? 2008-10-23.
Program zaliczeniowy polega na napisaniu aplikacji w C++. Celem aplikacji jest wykonywanie prostych 
programów na danych.
Programem nazywamy listę kolejnych operacji na danych.
Każdy program jest postaci:
operacja 
operacja 
....
operacja 
Każda operacja jest pewnym przekształceniem plików z danymi.
Są dostępne następujące operacje:
? Operacja filtrowania
? Składania: FILTER     .
?  =, !=, >, =, <=.
? Schemat pliku wynikowego jest taki sam jak źródłowego.
? Operacja dołączenia
? Składnia: MERGE   
? Operacja polega na zsumowaniu kolumn plików 1 i 2.
? Operacja powiedzie się jeśli kolumny plików 1 i 2 mają inne nazwy oraz ilość wierszy w pliku 1 i 
w pliku 2 jest taka sama.
? Wynikowy plik ma wszystkie kolumny pliku 1 i wszystkie kolumny pliku 2.
? Operacja łączenia
? Składnia: JOIN   
? Operacja polega na wypisaniu do pliku docelowego najpierw zawartości pliku1 a za nim pliku2.
? Operacja jest wykonalna tylko i wyłącznie, gdy ilość kolumn pliku1 i pliku2 jest taka sama i typy 
kolejnych kolumn są takie same.
? Wynikowy plik ma schemat taki sam jak plik1.
? Operacja wyliczenia
? Składnia: AGREGATE     
?  oznacza operację z listy: maksimum [MAX], minimum [MIN], suma [SUM], średnia 
[AVG] (zaokrąglenie do int'a), ilość [COUNT].
? Operacja powiedzie się jeśli typ danych jest zgodny z operacją.
? Wynikowy plik ma strukturę złożoną z jednej kolumny o podanej nazwie typu int oraz zawiera 
jeden wiersz z wynikiem operacji.
? Operacja dodania danych.
? Składnia: INSERT    ... 
? Operacja dodaje wiersz danych na końcu pliku danych.
? Operacja się powiedzie jeśli ilość danych zgadza się z listą kolumn oraz typu danych się 
zgadzają.
? Operacja ładowania danych.
? Składnia: LOAD   
? Operacja odczytuje linia po linii dane z pliku wejściowego i dopisuje je na końcu wskazanego 
pliku.
? Dane w pliku z danymi są zapisane linia po linii.
? Każda linia zawiera jeden rekord danych.? Każda linia zawiera pewną ilość pól postaci   ... 
? Każda wartość jest zapisana w formacie wartości przyjmowanym we wszystkich 
komendach.
? Operacja się powiedzie jeśli ilość danych zgadza się z listą kolumn oraz typu danych się 
zgadzają.
? Operacja stworzenia pustego pliku.
? Składnia: CREATE    ... 
? Operacja tworzy pusty plik o podanej strukturze.
? Dodatkowa operacja wypisania pliku.
? Składnia: PRINT 
? Operacja nie posiada żadnego wyjścia.
? Operacja powinna wypisać na standardowe wyjście zawartość danego pliku (oczywiście w 
postaci zinterpretowanej).
? Dane powinny być wypisane wierszami. Pierwszy wiersz powinien być w postaci:   ...  
? Kolejne wiersze powinny zawierać kolejne wartości pól (w odpowiedniej kolejności) zapisanie w 
formacie , czyli np. 'M &38; M' oznacza wartość ?M & M?.
Legenda:
?  - pole postaci 'łańcuch znaków bez znaku ' , & oraz znaku nowej linii. Znaki ', & oraz 
nowej linii są zapisywane jako &;'
? Wszelkie nazwy plików, kolumn, etc. są ciągami znaków [a-z] i [A-Z] oraz [0-9] oraz znaku _ o 
długości maksymalnie 50 znaków.
?  oznacza typ danych. Są dwa typy, string ? oznacza łańcuch znaków dowolnej długości oraz 
int oznacza liczę 32 bitową ze znakiem.
Schemat działania aplikacji składa się z następujących kroków:
1. Wczytanie programu.
2. W pętli dla każdej komendy.
3. Wykonaj komendę.
Wykonanie każdej komendy polega na:
1. Wczytaniu plików źródłowych do pamięci.
2. Wykonanie komendy w pamięci na danych w pamięci.
3. Zapis danych do plików docelowych.
Aplikacja powinna zapisywać wszelkie dane w lokalnym katalogu. Każdy błąd w programie jest 
krytyczny i powinien przerywać działanie aplikacji. Program powinien być wczytywany ze 
standardowego wejścia. Wszelkie błędy odczytu/zapisu na dysk są błędami krytycznymi. Struktura 
danych w plikach dowolna, wg własnych pomysłów. Optymalizacja implementacji komend nie jest 
priorytetem. Można założyć, że w każdej chwili działania programu całość danych w plikach mieści się 
w pamięci. W plikach nie może być wartości NULL.
Przykład programu:
CREATE tabela1 dzial string zarobki int
INSERT tabela1 tabela1 'Zarząd' '10000'
INSERT tabela1 tabela1 'Zarząd' '15000'
INSERT tabela1 tabela1 'Zarząd' '12000'
INSERT tabela1 tabela1 'IT' '4000'
INSERT tabela1 tabela1 'Administracja' '2000'
INSERT tabela1 tabela1 'IT' '4000'INSERT tabela1 tabela1 'Zarząd' '19000'
INSERT tabela1 tabela1 'IT' '5000'
FILTER tabela2 tabela1 dzial = 'Zarząd'
AGREGATE tabela3 tabela2 zarobki SUM zarobki
FILTER tabela2 tabela1 dzial = 'IT'
AGREGATE tabela4 tabela2 zarobki SUM zarobki
JOIN tabela3 tabela3 tabela4
PRINT tabela3
Po wykonaniu programu w tabeli 3 powinny być dwa wiersze. Pierwszy powinien zawierać sumę 
zarobków zarządu zaś drugi sumę zarobków działu IT.
Po wypisaniu na standardowym wyjściu powinno być:
zarobki int
'56000'
'13000'


Oficjalne ? wiążące FAQ do zadania.
1. Jakie znaki mogą się pojawić w nazwach plików (plików wejściowych, plikach wyjściowych i 
plikach do ładowania danych) i nazwach kolumn (kolumny w plikach)?
Odp: W nazwach mogą się pojawiać tylko angielskie literki małe (a, b, c, ..., z), angielskie literki 
duże (A, B, C, ..., Z), cyfry (0, 1, ..., 9) oraz znak podkreślenia ( _ ). Nie może być ani spacji ani 
polskich znaków. Maksymalna długość to 50 znaków (liczona jako ilość znaków w nazwie). W 
związku z potencjalnymi problemami z systemem plików, na którym uruchamiany jest program 
zakłada się, że program może w zakresie rozróżniania wielkości liter w nazwach plików polegać 
na systemie plików. Czyli jest dopuszczalne, że pliki 'Ala.db', 'ALA.db' i 'ala.DB' odnoszą się w 
istocie do tego samego pliku i podanie jakiejkolwiek z tych nazw powoduje odczytanie tego 
samego pliku. Natomiast nie jest dopuszczalne, aby polecenie zapisania pliku 'Ala.db' w istocie 
zapisywało plik 'ALA.DB', choć jeśli taki plik istnieje to może zostać nadpisany.
2. Jakie znaki mogą się znaleźć w wartościach danych?
Odp: Każda wartość jest zapisana w postaci napisu ograniczonego znakami apostrofa (' - znak 
o kodzie 39). We wnętrzu napisu nie występują znaki apostrofa ( ' ) oraz nowej linii (znaki o 
kodach 13 i 10). Ponadto każdy znak może być reprezentowany w postaci &; przy 
czym  jest z zakresu od 1 do 255. Co więcej znak & musi być reprezentowany w ten 
sposób. Np. wartość M'c ma kota &John's ma psa może zostać zapisana jako: 
'M&39;c ma kota &38;&13;&10;John&39;s ma psa' albo jako '&77;&39;&99;&32;ma&32;kota 
&38;&13;&10;John&39;s ma&32;psa'. Natomiast nie poprawne są napisy: 'M&390;c ma kota 
&38;&13;&10;John's ma psa' (niepoprawne wartość 390 oraz niepoprawny znak ' w środku 
napisu), 'M&39;c ma kota &&13;&10;John&39;s ma psa' (niepoprawny znak &) oraz 'M&39;c 
ma kota &38;John&39;s ma psa' (nowa linia w środku napisu).
3. Czy program powinien obsługiwać BOM w plikach i czy powinien obsługiwać pliki zapisane w 
UTF-8, UTF-16, itd.?
Odp: Nie, zakłada się, że program wczytywany ze standardowego wejścia jest zapisany w 
formacie ASCII, nie zawiera BOM. Pliki danych w komendzie LOAD nie posiadają BOM są 
zapisane w formacie ASCII. Nie specyfikujemy, w jakim kodowaniu są znaki w aplikacji (np. 
ISO-8559-1, ISO-8559-2, WINDOWS-1250), ale autor aplikacji powinien być w stanie 
odpowiedzieć jak kwestia kodowania wpływa na działanie aplikacji. Pliki danych są w pełni 
zdefiniowane przez aplikację, więc format ich zapisu jest dowolny.
4. Jak aplikacja powinna się zachować w przypadku problemów w czasie wykonania programu?
Odp: Aplikacja powinna obsługiwać normalne błędy, które mogą się pojawić w czasie działania 
aplikacji, czyli np. błędne formaty komend, błędne formaty plików, brak plików i brak praw 
dostępu do plików. W przypadku natrafienia na problem w czasie wykonania użytkownik 
powinien zostać poinformowany o charakterze problemu (czyli opis problemu w taki sposób, 
aby użytkownik zrozumiał i był w stanie coś zaradzić) oraz o miejscu wystąpienia problemu (np. 
jeśli problem pojawił się przy wykonywaniu komendy, to należy poinformować użytkownika, 
jakiej komendy dotyczy problem). Po wyświetleniu informacji o błędzie aplikacja powinna 
zakończyć działanie.
5. Co to znaczy, że komendy w programie powinny być transakcyjne?
Odp: Oznacza to, że wykonanie każdej komendy może się powieść lub nie. W przypadku, gdy 
wykonanie komendy nie powiodło się aplikacja powinna przywrócić stan sprzed rozpoczęcia 
wykonania komendy. W szczególności oznacza to usunięcie wszelkich plików tymczasowych. 
Nie dopuszcza się częściowego wykonania komendy polegającego np. na częściowym 
załadowaniu danych w komendzie LOAD albo częściowej agregacji danych w komendzie 
AGREGATE.
6. Czy lista   w poleceniu CREATE może być pusta czy tez nie? Innymi słowy 
czy możemy stworzyć plik bez żadnych kolumn?
Odp: Nie. W poleceniu CREATE lista kolumn musi zawierać co najmniej jeden element.7. Czy w operacje w poleceniu AGREGATE (max, min) w przypadku gdy plik/tabelka są puste 
mogą zwracać 0? Czy bardziej należy rozumieć to jako błąd (nie ma wierszy więc taka operacja 
liczenia max wartości z jakiejś kolumny jest w ogóle niemożliwa)? 
Odp: Polecenie powinno powodować błąd w przypadku, gdy operacja nie ma sensu. Operacje 
suma i średnia (SUM i AVG) mają sens tylko dla kolumn typu liczbowego. Operacje MIN, MAX 
i COUNT mogą być wykonane dla kolumny dowolnego typu. W przypadku MIN i MAX dla 
tekstów należy użyć tej samej relacji porządkowania tekstów co w poleceniu FILTER. Ponadto 
operacje MIN, MAX oraz AVG mają sens tylko dla niepustego zbioru. Operacje COUNT oraz 
SUM mają sens zarówno dla zbioru pustego jak i niepustego. W przypadku zbioru pustego 
zarówno COUNT jak i SUM zwraca 0.
8. Czy wartość '' jest dozwolona i co reprezentuje?
Odp: Taka wartość jest poprawna i reprezentuje napis długości 0 znaków (pusty napis).
9. Czy w operacji PRINT wartości powinny być wyświetlane w postaci zinterpretowanej i co to 
oznacza?
Odp: Tak, PRINT powinien wyświetlać wartości w postaci zinterpretowanej. Oznacza to, że 
sekwencje znaków, które kodują inny znak, np. &38;, powinny być napisane jako znak, który 
kodują a nie sekwencja kodująca. Np. napis 'M &38; M' powinien być przez PRINT wypisany 
jako 'M & M.
10. Czy operacja FILTER działa na tekstach?
Odp: Tak.
11. Czy jest w jakikolwiek sposób określone w jaki sposób aplikacja powinna wewnętrznie 
przechowywać wartości?
Odp: Nie. Aplikacja wewnętrznie może przechowywać wartości jakkolwiek. Oczywiście 
wewnętrzna reprezentacja może ułatwić lub utrudnić implementację wymaganych operacji na 
danych. Decyzja całkowicie należy do programisty.
12. Czy można założyć, ze w poleceniu FILTER operacja jest otoczona białymi znakami? Innymi 
słowy czy np. dzial='12343' (bez spacji oddzielających) przechodzi czy możemy wywalić błąd?
Odp: Aplikacja powinna przyjmować co najmniej programy, które posiadają pojedynczą spację 
pomiędzy elementami komendy. Czyli np. FILTER a b test = '15'. Dodatkowym atutem 
aplikacji będzie akceptowanie dowolnej ilości znaków białych pomiędzy elementami komendy. 
Zaś akceptowanie w miejscach, gdzie jest to możliwe, komend bez spacji jest cechą aplikacji 
bardzo dobrych. To samo dotyczy wszystkich komend a nie tylko komendy FILTER.
13. W zadaniu w opisie polecenia AGREGATE ostatnia linijka mówi: ?Wynikowy plik ma strukturę 
złożoną z jednej kolumny o podanej nazwie TYPU INT". Czy należy rozumieć, że plik 
stworzony przez AGREGATE może mieć w wyniku zarówno int jak i string?
Odp: Tak, w treści zadania jest błąd. Odpowiedź na pytanie 7 jest wiążąca i jej skutkiem jest to, 
że w wyniku operacji AGREGATE z funkcją MIN lub MAX na kolumnie typu string w pliku, 
wynikowym powstaje kolumna typu string.
14. Jakie mogą być typy wynikowe kolumny w operacji AGREGATE?
Odp: Dla funkcji COUNT, SUM i AVG wynikowa kolumna ma typ int. Dla funkcji MIN i 
MAX typu kolumny wynikowej jest taki sam jak typ kolumny, na której jest wykonywana 
funkcja. Oczywiście powyższe ustalenia mają sens tylko wtedy, gdy operacja ma sens, czyli tylko 
w sytuacja, które opisuje odpowiedź na pytanie 7.
15. Kiedy jest termin oddania zadania zaliczeniowego?
Odp: Ostateczny termin oddania mija 15 grudnia (2008-12-15). Programy oddanie po tym 
terminie nie będą rozpatrywane. Zaleca się, aby oddać program przed ostatnimi zajęciami, aby 
była szansa rozmowy na temat programu na ostatnich zajęciach.
16. Czy możemy milcząco założyć, że wewnątrz pliku mogą się pojawiać tylko takie znaki jak 
wymieniono tj. spacje, A-Za-z_0-9 oraz pomocnicze znaki & ; oraz apostrofy ' ' okalające 
wartość. Czy musimy to sprawdzać?
Odp: Zdecydowanie nie. W pliku mogą się pojawić wszystkie znaki o kodach ASCII od 0 do 
255. Trzeba rozróżnić dwie kwestie, specyfikację poprawności wejścia i założenie, że wejście jest 
zgodne ze specyfikacją. W naszym zadaniu jest wyspecyfikowane jakie wejście jest poprawne, ale nie ma założenia, że dane na wejściu spełniają tą specyfikację. Oczywiście jeśli dane na wejściu 
są niepoprawne to użytkownik powinien dostać odpowiedni komunikat.
17. Tak naprawdę nie widzę różnicy między operacją JOIN a LOAD. Z tego co widzę to operacja 
LOAD robi to samo co JOIN. Czy różnica polega na tym ze LOAD łączy dwa pliki: plik1 i 
plik2 w wynikowy plik1. Natomiast JOIN łączy plik1 i plik2 w nowy plik wynikowy plik3. Czy 
poprawnie to rozumiem?
Odp: Źle rozumiesz. Chodzi o to, że specyfikacja w żaden sposób nie opisuje formatu 
wewnętrznego plików, na których operuje program (chodzi o pliki źródłowe/wynikowe we 
wszystkich komendach). Więc JOIN w istocie robi to samo co LOAD, ale w komendzie LOAD 
plik, z którego dane są ładowane ma określony format (być może inny niż pliki z danymi, być 
może taki sam, to zależy od programisty).
18. Czy w operacji FILTER i AGREGATE może się zdarzyć sytuacja, że plikiem wynikowym 
będzie plik, z którego biorę dane do przetworzenia, czyli na przykład: AGREGATE plik1 plik1 
zarobki SUM zarobki, czy zawsze to będzie nowy plik?
Odp: Nie ma żadnych założeń, czy jest to inny czy ten sam plik, więc może być inny i może być 
ten sam. Więcej informacji, patrz odpowiedź na pytanie 5.
19. Operacja JOIN i MERGE może mieć więcej niż dwie tabele do połączenia/zsumowania, na 
przykład: JOIN     ... ?
Odp: Nie, specyfikacja mówi, że operacja łączy dokładnie dwie tabele.
20. Czy w wartościach pól mogą pojawić się polskie literki?
Odp: Tak. Trzeba widzieć różnice pomiędzy wartościami a nazwami. Wartości występują 
wszędzie tam, gdzie dodajemy dane np. do kolumny, przy filtrowaniu, itp. Np. w INSERT 
tabela1 tabela1 'Zarząd' '1000' tabela1 to nazwa tabeli zaś 'Zarząd' to wartość. W wartościach 
mogą występować polskie literki jak i inne dziwne znaki np. %, $, /, [, ], itd. itd. zaś w nazwach 
(kolumn, plików) mogą występować tylko i wyłącznie normalne znaki tak jak to mówi 
specyfikacja, czyli [a-z] i [A-Z] oraz [0-9] oraz znak _.

A oto rozwiązanie:

include 
include 
include 
include 
include 
define round(x) (x<0?ceil((x)-0.5):floor((x)+0.5))

const int ERR_FILE=1;
const int ERR_LAST_TYPE_MISSING=2;
const int ERR_BAD_TYPE=3;
const int ERR_NUM_ROWS=4;
const int ERR_NAME=5;
const int ERR_TYPE=6;
const int ERR_NUM_COL=7;
const int ERR_AGGR=8;
const int ERR_AMP=9;
const int ERR_ASCII=10;
const int ERR_APO=11;
const int ERR_NAME_LEN=12;
const int ERR_NAME_CHAR=13;
const int ERR_COMM=14;

using namespace std;

	int str2int(string wartosc)
	{
		int liczba=0;
		for(int i=0;i='0')&&(wartosc[i]<='9'))
			{
				liczba=liczba*10+(wartosc[i]-'0');
			}
		}
		return liczba;
	}

	void my_itoa(int value, string& buf, int base){
		
		int i = 30;
		
		buf = "";
		
		for(; value && i ; --i, value /= base) buf = "0123456789abcdef"[value % base] + buf;
		
	}


	string AsciiEncode(string wartosc_string)
	{
		string zwroc="";
		//zamieniamy ' & ; n
		for(int i=0;i")
		{
			if(typ=="int")
			{
				if(wartosc_int>liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string>wartosc)
				{
					wynik=1;
				}
			}
		}
		else if(operacja==">=")
		{
			if(typ=="int")
			{
				if(wartosc_int>=liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string>=wartosc)
				{
					wynik=1;
				}
			}
		}
		else if(operacja=="<=")
		{
			if(typ=="int")
			{
				if(wartosc_int<=liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string<=wartosc)
				{
					wynik=1;
				}
			}
		}
		else if(operacja=="=")
		{
			if(typ=="int")
			{
				if(wartosc_int==liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string==wartosc)
				{
					wynik=1;
				}
			}
		}
		else if(operacja=="!=")
		{
			if(typ=="int")
			{
				if(wartosc_int!=liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string!=wartosc)
				{
					wynik=1;
				}
			}
		}
		else if(operacja=="<")
		{
			if(typ=="int")
			{
				if(wartosc_int<liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string<wartosc)
				{
					wynik=1;
				}
			}
		}
		else
		{
			wynik=-1; //nieznany operator.
		}

		return wynik;
	}

	string Wypisz_typ()
	{
		return nazwa+" "+typ;
	}

	string Wypisz(int zamien)
	{
		string zwroc="";
		
		if(zamien)
		{
			zwroc=AsciiEncode(wartosc_string);
		}
		else
		{
			zwroc=wartosc_string;
		}

		
		return "'"+zwroc+"'";
	}


}; // Koniec klasy Pole.




//Klasy reprezentujace wiersze tabel

class Wiersz
{
	public:
	vector  pola;
	Wiersz(vector  dane) : pola(dane){}
	Wiersz() {}
	string Wypisz(int zamien)
	{
		string wypisz="";
		int ile=pola.size();
		for(int i=0;i0)
		{
			wypisz+=pola.at(ile-1).Wypisz(zamien);
		}


		return wypisz;
	}
}; // Koniec klasy Wiersz.




//Klasa reprezentujaca tabele z danymi.
class Tabela
{

public:
	vector  wiersze;
	vector  typy;

	void Czysc()
	{
		wiersze.clear();
		typy.clear();
	}

	Pole Agreguj(string funkcja,string kolumna)
	{
		int kol=Kolumna(kolumna);
		Pole wynik;
		int suma=0;
		int min=0;
		int max=0;
		string min_str="";
		string max_str="";

		if(kol==-1)
		{
			
			wynik.typ="blad";
		}
		else
		{
			min=wiersze.at(0).pola.at(kol).wartosc_int;
			max=min;
			min_str=wiersze.at(0).pola.at(kol).wartosc_string;
			max_str=min_str;
			

			for(int i=0;i<wiersze.size();i++)
			{
				suma+=wiersze.at(i).pola.at(kol).wartosc_int;

				//min
				if(wiersze.at(i).pola.at(kol).wartosc_int<min)
				{
					min=wiersze.at(i).pola.at(kol).wartosc_int;
				}

				if(wiersze.at(i).pola.at(kol).wartosc_stringmax)
				{
					max=wiersze.at(i).pola.at(kol).wartosc_int;
				}

				if(wiersze.at(i).pola.at(kol).wartosc_string>max_str)
				{
					max_str=wiersze.at(i).pola.at(kol).wartosc_string;
				}
			}


			if(funkcja=="COUNT")
			{
				wynik.wartosc_int=wiersze.size();
				my_itoa(wiersze.size(),wynik.wartosc_string,10);
				wynik.typ="int";
			}
			else if(funkcja=="MAX")
			{
				wynik.typ=typy.at(kol).typ;
				if(wynik.typ=="int")
				{
					wynik.wartosc_int=max;
					my_itoa(max,wynik.wartosc_string,10);
				}
				else
				{
					wynik.wartosc_string=max;
				}
				
			}
			else if(funkcja=="MIN")
			{
				wynik.typ=typy.at(kol).typ;
				if(wynik.typ=="int")
				{
					wynik.wartosc_int=min;
					my_itoa(max,wynik.wartosc_string,10);
				}
				else
				{
					wynik.wartosc_string=min;
				}
				
			}
			else if((funkcja=="AVG")&&(typy.at(kol).typ=="int"))
			{
				wynik.typ="int";
				wynik.wartosc_int=round(suma/wiersze.size());
				my_itoa(wynik.wartosc_int,wynik.wartosc_string,10);
			}
			else if((funkcja=="SUM")&&(typy.at(kol).typ=="int"))
			{
				wynik.typ="int";
				wynik.wartosc_int=suma;
				my_itoa(wynik.wartosc_int,wynik.wartosc_string,10);
			}
			else
			{
				wynik.typ="blad";//blad.
			}

			
		}

		return wynik;
	}

	int Kolumna(string nazwa)
	//zwraca numer kolumny.
	{
		int znalezione=-1; //blad.
		for(int i=0;i<typy.size();i++)
		{
			if(typy.at(i).nazwa==nazwa)
			{
				znalezione=i;
				break;
			}
		}
		return znalezione;
	}

	int Filtruj(string kolumna, string operacja, string wartosc)
	{
		int blad=0;
		int kol=Kolumna(kolumna);

		if(kol!=-1)
		{
			for(int i=0;i<wiersze.size();i++)
			{
				
				int odp=wiersze.at(i).pola.at(kol).Porownaj(operacja,wartosc);
				if(odp==-1)
				{
					blad=61; //zly operator.
					break;
				}
				else if(odp==0)
				{
					wiersze.erase(wiersze.begin()+i,wiersze.begin()+i+1);
					i=i-1;
				}
			}
		}
		else
		{
			blad=51; //nie ma takiej kolumny.
		}

		return blad;
	}

	int Serializuj(string nazwa)
	{
		int blad=0;
		fstream plik;
		plik.open((nazwa+"_data.txt").c_str(),ios::out);
		if(plik.good())
		{

			plik<<"CREATE "<<nazwa<<" ";
			//zapisujemy.
			//Najpierw typy.
			for(int i=0;i<typy.size();i++)
			{
				plik<<"'"<<typy.at(i).nazwa<<"' "<<typy.at(i).typ<<" ";
			}
			plik<<"n";

			//Teraz dane.
			for(int i=0;i<wiersze.size();i++)
			{
				plik<<"INSERT "<<nazwa<<" "<<nazwa<<" "<<wiersze.at(i).Wypisz(1)<<"n";
			}

			plik.close();
		}
		else
		{
			blad=41;//nie ma dostepu do pliku.
		}

		return blad;
	}

	int Dodaj(vector  pola)
	{
		Wiersz w;
		w.pola=pola;
		wiersze.push_back(w);
		return 0;
	}

	int Utworz(vector  typ,int poczatek)
	{
		int blad=0;

		for(int i=poczatek;i<typ.size();i+=2)
		{
			typy.push_back(Pole(typ.at(i),typ.at(i+1),"1"));
		}
		
		return blad;
	}

	int Wstaw(vector dane,int poczatek)///////////////////////
	{
		int blad=0;

		vector tmp; 
		if(dane.size()-poczatek==typy.size())
		{
			for(int i=poczatek;i<dane.size();i++)
			{
				Pole tymczas=Pole(typy.at(i-poczatek).nazwa,typy.at(i-poczatek).typ,dane.at(i));
				tmp.push_back(tymczas);
				
			}
			
			if(blad==0)
			{
				Dodaj(tmp);
			}
		}
		else
		{
			blad=11; //Niepoprawna ilosc danych
		}
		return blad;
	}

	void Wypisz()
	{
		//Wypisujemy typy
		for(int i=0;i<typy.size();i++)
		{
			cout<<typy.at(i).Wypisz_typ()<<" ";
		}
		cout<<"n";

		//Teraz wiersze
		int ile=wiersze.size();
		for(int i=0;i<ile;i++)
		{
			cout<<wiersze.at(i).Wypisz(0)<<"n";
		}
	}

}; // Koniec klasy tabela.




class Parser
{
private:
	vector  klucze;
	string komenda;
public:
	int blad;		//Kod bledu.
	Tabela tabelka1;
	Tabela tabelka2;

	Parser() : blad(0){}

	void Czysc()
	{
		tabelka1.Czysc();
		tabelka2.Czysc();
		klucze.clear();
		komenda="";
	}

	int Wczytuj(string nazwa)
	{
		fstream plik;
		plik.open((nazwa+"_data.txt").c_str(),ios::in);
		if(plik.good())
		{
			string dane;
			while(getline(plik,dane))
			{
				Wykonaj(dane);
			}
			
			plik.close();
		}
		else
		{
			blad=ERR_FILE;
			cout<<"Problem z plikiem wejsciowym n-----n"<<komenda;
			throw(ERR_FILE);
		}
		
		return blad;
	}

	Tabela Deserializuj(string nazwa)
	{
		Parser pars;
		blad=pars.Wczytuj(nazwa);
		return pars.tabelka1;
	}

	int Insert()
	{
		Nazwa(1);
		Nazwa(2);
		tabelka1=Deserializuj(klucze.at(2));
		blad=tabelka1.Wstaw(klucze,3);

		if(blad==0)
		{
			blad=tabelka1.Serializuj(klucze.at(1));
		}

		return blad;
	}

	int Create()
	{
		for(int i=2;iklucze.size()-1)
			{
				cout<<"Brak typu ostatnigon-------n"<<komenda;
				blad=ERR_LAST_TYPE_MISSING;
				throw(blad);
			}
			else if((klucze.at(i+1)!="string")&&(klucze.at(i+1)!="int"))
			{
				cout<<"Nieprawidlowy typn-------n"<<komenda;
				blad=ERR_BAD_TYPE; //Nieprawidlowy typ.
				throw(blad);
			}
		}

		if(blad==0)
		{
			blad=tabelka1.Utworz(klucze,2);
		}

		if(blad==0)
		{
			blad=tabelka1.Serializuj(klucze.at(1));
		}


		return blad;
	}

	int Filter()
	{
		//Filtruje.
		//Czytamy tabele do przefiltrowania
		tabelka1=Deserializuj(klucze.at(2));
		//Usuwamy niepasujace wiersze
		blad=tabelka1.Filtruj(klucze.at(3),klucze.at(4),klucze.at(5));
		//Zapisujemy:
		blad=tabelka1.Serializuj(klucze.at(1));
		return blad;
	}

	int Load()
	{
		//Laduje dane.
		Parser parserek;
		string wiersz;
		//Otwieramy plik:
		fstream plik;
		tabelka1=Deserializuj(klucze.at(2));
		if (blad==0)
		{
			plik.open(klucze.at(3).c_str(),ios::in);
			if(plik.good())
			{
				
				//Zwalimy robote na juz napisana funkcje:
				while((blad==0)&&(getline(plik,wiersz)))
				{
					blad=parserek.Przetworz(wiersz);

					if(blad==0)
					{
						blad=tabelka1.Wstaw(parserek.klucze,0);
					}
				}

				if(blad==0)
				{
					blad=tabelka1.Serializuj(klucze.at(1));
				}
			}
			else
			{
				cout<<"Problem z plikiem wejsciowym n-----n"<<komenda;
				blad=ERR_FILE;
				throw(blad);
			}
		}
		else
		{
			cout<<"Problem z plikiem wejsciowym n-----n"<<komenda;
			blad=ERR_FILE;
			throw(blad);
		}

		return blad;
	}

	int Merge()
	{
		tabelka1=Deserializuj(klucze.at(2));
		if(blad==0)
		{
			
			tabelka2=Deserializuj(klucze.at(3));
			if(blad!=0)
			{
			}
			else if(tabelka1.wiersze.size()==tabelka2.wiersze.size())
			{
				for(int i=0;i<tabelka1.typy.size();i++)
				{
					if(tabelka1.typy.at(i).nazwa==tabelka2.typy.at(i).nazwa)
					{
						blad=72;//taka sama nazwa.
						break;
					}
				}

				if(blad==0)
				{
					//Dopisujemy typy
					tabelka1.typy.insert(tabelka1.typy.end(),tabelka2.typy.begin(),tabelka2.typy.end());
					//Dopisujemy kolumny.
					for(int i=0;i<tabelka2.wiersze.size();i++)
					{
						tabelka1.wiersze.at(i).pola.insert(tabelka1.wiersze.at(i).pola.end(),tabelka2.wiersze.at(i).pola.begin(),tabelka2.wiersze.at(i).pola.end());
					}
					//zapisujemy:
					tabelka1.Serializuj(klucze.at(1));
				}
			}
			else
			{
				cout<<"Zła liczba wierszy n-----n"<<komenda;
				blad=ERR_NUM_ROWS;
				throw(blad);
			}
		}
		return blad;
	}

	int Join()
	{
		tabelka1=Deserializuj(klucze.at(2));
		if(blad==0)
		{
			
			tabelka2=Deserializuj(klucze.at(3));
			if(blad!=0)
			{
			}
			else if(tabelka1.typy.size()==tabelka2.typy.size())
			{
			
				for(int i=0;i<tabelka1.typy.size();i++)
				{
				
					if(tabelka1.typy.at(i).nazwa!=tabelka2.typy.at(i).nazwa)
					{
						cout<<"Zła nazwa n-----n"<<komenda;
						blad=ERR_NAME;
						throw(blad);
					}
					else if(tabelka1.typy.at(i).typ!=tabelka2.typy.at(i).typ)
					{
						cout<<"Zły typ n-----n"<<komenda;
						blad=ERR_TYPE;
						throw(blad);
					}
				}

				if(blad==0)
				{
					//Dopisujemy wiersze.
					for(int i=0;i<tabelka2.wiersze.size();i++)
					{
						tabelka1.wiersze.push_back(tabelka2.wiersze.at(i));
					}
					//zapisujemy:
					tabelka1.Serializuj(klucze.at(1));
				}
			}
			else
			{
				cout<<"Zła liczba kolumn n-----n"<<komenda;
				blad=ERR_NUM_COL;
				throw(blad);
			}
		}

		return blad;
	}

	int Agregate()
	{
		tabelka1=Deserializuj(klucze.at(2));
		Pole wynik=tabelka1.Agreguj(klucze.at(4),klucze.at(5));
		
		if(wynik.typ=="blad")
		{
			cout<<"Problem agregacji n-----n"<<komenda;
			blad=ERR_AGGR;
			throw(blad);
		}
		else
		{
			wynik.nazwa=klucze.at(3);
			//Tworzymy tabelke z wynikiem.
			vector tmp;
			tmp.push_back(wynik);
			tabelka2.typy=tmp;
			tabelka2.Dodaj(tmp);
			tabelka2.Serializuj(klucze.at(1));
		}

		return blad;
	}

	int Print()
	{
		tabelka1=Deserializuj(klucze.at(1));
		tabelka1.Wypisz();
		return blad;
	}


	int Przetworz(string polecenie)
	//Przetwarza polecenia na wektor z tokenami.
	{
		komenda=polecenie;
		polecenie.insert(polecenie.end(), 1, ' ');//spacja na koniec.
		int ile=polecenie.length();
		string teraz="";
		string tmp;
		int otwarty=0; // otwarty apostrof.
		int kod=0;

		klucze.clear();

		//Przetwarzamy polecenie litera po literze.
		for(int i=0;i<ile;i++)
		{
			if(polecenie[i]=='&')
			{
				kod=0;
				//zamieniamy na ascii.
				i++;
				while((polecenie[i]!=';')&&(i<ile))
				{
					kod=kod*10+(polecenie[i]-'0');
					i++;
				}

				if(i==ile)
				{
					cout<<"Niedokończone & n-----n"<<komenda;
					blad=ERR_AMP;
					throw(blad);
				}
				else if((kod255))
				{
					cout<<"Zły kod ASCII n-----n"<0)
				{
					klucze.push_back(teraz);
					teraz="";
				}
			}
			else
			{
				teraz.insert(teraz.end(), 1, polecenie[i]);
			}

		}

		if(otwarty==1)
		{
			cout<<"Niedokończony apostrof n-----n"<50)
			{
				cout<<"Za długa nazwa n-----n"<<komenda;
				blad=ERR_NAME_LEN;
				throw(blad);
			}
			else
			{
				for(int i=0;i='a')&&(tmp[i]='A')&&(tmp[i]='0')&&(tmp[i]<='9'))))
					{
						cout<<"Zły znak w nazwie n-----n"<<komenda;
						blad=ERR_NAME_CHAR;
						throw(blad);
					}
				}
			}
		}
		return blad;
	}


	int Zrob()
	{

			if(klucze.at(0)=="INSERT")
			{
				blad=Insert();
			}
			else if(klucze.at(0)=="CREATE")
			{
				blad=Create();
			}
			else if(klucze.at(0)=="FILTER")
			{
				blad=Filter();
			}
			else if(klucze.at(0)=="AGREGATE")
			{
				blad=Agregate();
			}
			else if(klucze.at(0)=="JOIN")
			{
				blad=Join();
			}
			else if(klucze.at(0)=="PRINT")
			{
				blad=Print();
			}
			else if(klucze.at(0)=="MERGE")
			{
				blad=Merge();
			}
			else if(klucze.at(0)=="LOAD")
			{
				blad=Load();
			}
			else
			{
				cout<<"Nieznana komenda n-----n"<<komenda;
				blad=ERR_COMM;
				throw(blad);
			}
		return blad;
	}


	int Wykonaj(string polecenie)
	{
		Przetworz(polecenie);
		
		if(blad==0)
		{
			Zrob();
		}

		return blad;
	}


};  // Koniec klasy Parser.





int main()
{
	Parser pars;
	string wiersz;

	int blad=0;
	while((blad==0)&&(getline(cin,wiersz)))
	{	
		pars.Wykonaj(wiersz);
		blad=pars.blad;
		pars.Czysc();
	}

	return 0;
}



Kod źródłowy