Program ma byc kalkulatorem operujacym na liczbach calkowitych (na
zmiennoprzecinkowe jest go dosc latwo przerobic). Program wczytuje wyrazenie
arytmetyczne z pliku podanego w linii polecen. Dla pewnego uproszczenia
zalozylem, ze uzytkownik poprawnie skonstruowal plik wejsciowy, czyli:
1) ilosc nawiasow otwierajacych i zamykajacych zgadza sie
2) miedzy dwoma znakami dzialan stoi liczba lub nawias (wyjatkiem jest
   operator zmiany znaku na przeciwny, on tego nie wymaga)
3) uzytkownik zastosowal znaki dzialan ^*/+- i normalne nawiasy okragle ()
Wszelkie znaki, ktorych program nie zna (m.in. spacja i tabulator) sa
ignorowane ("123#4" znaczy to samo, co "1234")
Rowniez dla uproszczenia przyjalem, ze wynik bedzie wypisywany na ekranie, ale
to jest latwo zmienic przy uzyciu funkcji fprintf.

Teraz slowko o zastosowanym przeze mnie algorytmie.

Normalny czlowiek (choc nie zdaje sobie z tego sprawy - ze jest normalny;))
wyrazenia arytmetyczne rozwiazuje przez zamienianie najpierw tego, co jest w
najbardziej wewnetrznych nawiasach, ew. przez opuszczanie nawiasow. Komputer
tak nie potrafi, a przynajmniej jest to dla niego trudne. Prostszym
rozwiazaniem jest jechanie po wyrazeniu od lewej do prawej. To tez moj program
robi.
Lecimy od lewej. Jesli napotkamy jakas liczbe, to ja zapamietujemy. Jesli
napotkamy znak dzialania, to zapamietujemy, ze mielismy go wykonac i jedziemy
dalej szukajac liczby. Mamy liczbe, ale za nia stoi dzialanie. Jesli to
dzialanie wazniejsze (np. mnozenie jest wazniejsze od dodawania), to
zapamietujemy, ze wczesniej mielismy wykonac to dzialanie (pamietajac, ze
poprzednie tez trzeba wykonac). Do zapamietywania dzialan sluzy stos dzialan
(wierzchnie dzialanie odpowiada ostatniemu zapamietanemu), natomiast o tym,
czy dane wyrazenie jest wazniejsze, mowi priorytet tego dzialania (lezacy na
drugim stosie). Jesli napotkalismy na rownie wazne dzialanie co ostatnie, to
mozemy to ostatnie wykonac, a na wyniku wykonac drugie (to jesli chodzi o plik
naglowkowy). Jesli napotkamy nawias otwierajacy, to wiemy, ze dzialanie/a
za tym nawiasem jest/sa wazniejsze - czyli jego/ich priorytet jest wiekszy.
Przy nawiasie zamykajacym dzieje sie na odwrot.
Napotykajac znak dzialania musimy najpierw wykonac dzialania wazniejsze lub
rownie wazne - z tych zapamietanych (lezacych na stosie). Ale juz mniej wazne
dzialania wykonaja sie po naszym aktualnym.
Mniej wiecej na takim rozumowaniu opiera sie idea programu. Nie twierdze, ze
jest to najszybszy sposob na przetwarzanie liczenie wyrazen arytmetycznych,
ale jest to jednak sposob skuteczny i niezbyt skomplikowany w implementacji
(zaprogramowaniu), co zawazylo na moim wyborze.


NOUN BUKZ:

* Program napotkawszy wyrazenie w stylu 1+*2 miedzy '+' a '*' wstawi 0, co
  moze spowodowac dziwne efekty. Jedynym przypadkiem, gdy nic sie zlego nie
  stanie jest 1*-2, co jest rozumiane jako 1*(-2). Oczywiscie gdyby chciec
  i ten typ wyrazen uwazac za nielegalny (co notabene sie dzieje w
  matematyce), to program mialby nieco prostsza konstrukcje (nie trzeba wtedy
  sprawdzac, czy poprzednik minusa jest cyfra lub zamknieciem nawiasu)
* Kod zrodlowy zajmuje chyba za duzo jak na taki prosty programik, ale nie
  wiem, jak to mozna zmienic w SENSOWNY sposob (nie sprowadzajac calego kodu
  do czterech dluuuuuuuuuuuugich linijek).

Program powstawal przez ok. 3 godziny (plus 30 minut na odtwarzanie glownego
pliku z powodu bledu w sztuce archiwizacji) - w tym miesci sie jakies
1/2 godziny na obmyslanie algorytmu (musialem sie pochwalic, jaki to ja zdolny
jestem ::::))))))

To chyba wszystko na ten temat.

                                                  Dozzie the Programmer

