Postać infiksowa jest powszechnie wykorzystywana w matematyce. Jednak dla komputerów o wiele wygodniejsze jest wczytać dwa argumenty i zastosować operator czyli skorzystać z postaci postfiksowej. W notacji postfiksowej nie ma potrzeby używania nawiasów co zdecydowanie skraca czas obliczeń i złożoność kodu je wykonującego.
W kodzie będę korzystać ze stosu, który został przeze mnie opisany tutaj. Istnieje możliwość dołączenia mojego rozwiązania do swojego projektu pobierając i dołączając do swojej aplikacji biblioteke stos.h, którą dołączamy do aplikacji przy pomocy dyrektywy include:
Zakładamy, że otrzymujemy od użytkownika napis, który zawiera liczby, stałe, operatory i znaki nawiasów. Między nimi mogą się pojawić spacje. Przykładowo dla:
Założenia wczytania danych i pokazania wyniku spełnia poniższy kod:
Zmienna BUFFER_SIZE jest opcjonalna. Wygodniej się zmienia rozmiar buforu w jednym, a nie w dwóch miejscach kiedy uznamy, że użytkownik powinien móc wprowadzić dłuższy ciąg znaków.
Żeby algorytm dobrze działał musimy wiedzieć czy dany znak jest operatorem, a jeśli tak to jaki jest jego priorytet. Funkcja priorytet() dla podanego znaku zwróci -1 jeśli to nie jest operator lub odpowiednią wartość między 0, a 3 jeśli jest to operator. Użyjemy do tego funkcji switch:
Jak już ustaliliśmy dostajemy ciąg znaków. Zakładamy, że wynik to napis, więc nagłówek funkcji to:
Nasz program będzie iterował każdy znak i odpowiednio go interpretował. Nie będziemy sprawdzać poprawności wejścia. Możemy założyć, że użytkownik wprowadza prawidłowy napis do konwersji.
Na początku (2.) tworzymy stos na którym będziemy odkładać operatory. Dalej tworzymy nową zmienną c, która będzie przechowywać napis wyjściowy. Potrzebujemy zadeklarować dwie zmienne: (4.) i, która posłuży do iteracji napisu wejściowego oraz ic, która będzie wskazywała, który znak napisu wyjściowego aktualnie nadpisujemy. (6.) I rozpoczynamy iterację napisu wejściowego.
Liczby i stałe zostaję przepisane od razu na wyjście, dlatego (8.) po sprawdzeniu, że mamy literę lub cyfrę rozpoczynamy (9. - 13.) przepisywanie na wyjście, aż będzie cyfra lub litera. Na sam koniec (14.) dopisujemy spację. Następnie sprawdzamy czy podany znak nie jest nawiasem. Jeśli jest to go dopisujemy na stos.
Należy pamiętać, aby zwiększyć zmienną i. Inaczej będziemy w kółko rozpatrywać ten sam znak. Zgodnie z listą kroków dalej sprawdzimy czy wczytany znak nie jest nawiasem zamykającym:
Jeśli jest to (18.) deklarujemy zmienną char, która będzie przechowywać operator zdjęty ze stosu. Wyjaśnienia wymaga tu kolejna linijka (19.). Zdejmuje ze stosu operator i go przypisujemy zmiennej t. Po tym sprawdzamy czy nie jest to (. Jeśli tak to pętla zostanie przerwana, a ( będzie zdjęty ze stosu i nie wypisany. Linijki (20. - 21.) to wypisywanie operatora i znaku spacji do wyjścia.
Przedostatni przypadek dotyczy pobrania operatora z wejścia:
Najpierw (28.) upewniamy się, że wczytujemy operator. Możemy to zrobić sprawdzając wartość funkcji prorytet(), która dla znaków nie operatora zwróci -1. Przed (29.) wrzuceniem wczytanego operatora do stosu musimy sprawdzić czy na stosie nie ma operatorów o niższym priorytecie niż wczytywany operator. Jeśli takie operatory są to wpierw (27. - 28.) musimy je wypisać.
Jeśli jednak znak nie spełnia żadnego wcześniejszego warunku to możliwe, że to np. znak spacji, który nie ma większego dla nas znaczenia, dlatego pominiemy interpretowanie go zwiększając zmienną i:
Po ostatnim warunku kończy się nasza pętla while, więc zamykamy ją.
Przed zwróceniem napisu wyjściowego musimy (36. - 37.) dopisać wszystkie operatory znajdujące się na stosie, aż (35.) będzie pusty. (39.) Zwalniamy pamięć, (40.) dopisujemy znak końca napisu i (41.) zwracamy napis.
Dodaj alias operatora dzielenia ":".
Dodaj alias nawiasów okrągłych ( ), aby na tej samej zasadzie były interpretowane nawiasy kwadratowe [ ].