Strona główna » Algorytmy » Artykuły » Ulepszone ONP
 

Ulepszone ONP

· Wprowadzanie · Rozszerzenie ·

Ulepszone ONP

Przed przeczytaniem artykułu proponuje zapoznać się z poprzednim artykułem o ONP. Tym razem rozszerzymy funkcjonalność programu o możliwość wprowadzania bezpośrednio liczb rzeczywistych oraz definiowania funkcji predefiniowanych.

Implementacja

Wczytywanie liczby rzeczywistej

Podany kod prawidłowo wczytywał liczbę do pamięci, a następnie umieszczał w stosie. Wyróżnia go rozpoznawanie czy liczba jest dodatnia czy ujemna.

  1.       bool minus = false;
  2.       if(input[i]=='-'){
  3.         minus = true;
  4.         i++;
  5.       }
  6.       double a = 0;
  7.       while(input[i]>='0' && input[i]<='9'){
  8.         a *= 10;
  9.         a += (input[i] - '0');
  10.         i++;
  11.       }
  12.       if(minus)
  13.         a *= -1;
  14.       push(st, a);

Jednak nie pozwala wprowadzić np. liczby rzeczywistej 2.2. Konkretniej chcemy, aby program po wczytaniu części całkowitej sprawdził czy nie ma części dziesiętnej. Część dziesiętna liczby będzie znajdować się po kropce.

Dodatkową część algorytmu dopiszemy po wczytaniu części dodatniej czyli zaczynamy dopisywać kod w linijce (13.). Poprzednia pętla kończy się, gdy zamiast cyfry pojawił się jakiś znak. To może być spacja, ale również kropka. (1.) Jeśli jest to kropka to rozpoczynamy wczytywanie części ułamkowej:

  1.       if(input[i]=='.'){
  2.         i++;
  3.         double mn = 1;
  4.         while(input[i]>='0' && input[i]<='9'){
  5.           mn /= 10;
  6.           a += ((double)(input[i] - '0')) * mn;
  7.           i++;
  8.         }
  9.       }

(2.) Zwiększamy wskaźnik, aby algorytm wczytał liczbę. (3.) Zmienna mn będzie nam przechowywać na której pozycji mamy umieścić cyfre w liczbie. (4. - 7.) Wczytujemy kolejne cyfry. Pamiętamy o zmianie pozycji, gdzie ma się znaleźć: (5.) dzielimy mn przez 10. (6.) Następnie dodajemy pobraną cyfre pomnożoną przez mn. Obowiązkowe jest tu castowanie na typ double pobranej cyfry, ponieważ inaczej wynikiem mnożenia jest liczba całkowita, która zawsze da 0. Po zakończeniu pętli program powinien przejść do linijki (14.) oryginalnego algorytmu.

Obsługa funkcji predefiniowanych

Do tej pory kod wykonywał określone operacje tylko dla operatorów. Jednak czasem potrzebne jest dopisanie bardziej zaawansowanej funkcji, która niekoniecznie przyjmuje dwa argumenty lub więcej. Częściowo przepiszemy fragment kodu z instrukcją switch:

  1.       switch(input[i]){
  2.         case '+':
  3.           push(st, t2 + t1);
  4.         break;
  5.         case '-':
  6.           push(st, t2 - t1);
  7.         break;
  8.         case '*':
  9.           push(st, t2 * t1);
  10.         break;
  11.         case '/':
  12.           push(st, t2 / t1);
  13.         break;
  14.         case '^':
  15.           push(st, pow(t2, t1));
  16.         break;
  17.       }

Tym razem już nie będziemy pobierać wartości ze stosu do zmiennych. Na sam koniec instrukcji dodamy co ma zrobić program kiedy znak nie jest operatorem.

  1.         default:
  2.           char* function = new char[8];
  3.           int j = 0;
  4.           while(input[i]>='a' && input[i]<='z' && j < 7){
  5.             function[j++]=input[i++];
  6.           }
  7.           function[j]='\0';
  8.           if(strcmp(function, "cos") == 0){
  9.             push(st, cos(pop(st)));
  10.           } else if(strcmp(function, "sin") == 0){
  11.             push(st, sin(pop(st)));
  12.           }
  13.         break;

Przed zakończeniem instrukcji switch dopisujemy przypadek default:. Oznacza to, że kod w tym zawarty zostanie wykonany kiedy wczytywany znak nie jest operatorem. Po rozpoznaniu takiego przypadku (2.) zadeklarujemy zmienną function, która będzie rodzajem buforu przechowującego nazwę funkcji. (4. - 6.) Przy pomocy pętli wczytujemy każdy mały znak alfabetu łacińskiego. (7.) Na sam koniec dopisujemy znak końca napisu, który będzie bardzo ważny przy porównywaniu tekstu. (8.) Następnie sprawdzamy przy pomocy funkcji strcmp czy napis wczytany i nazwa predefiniowana są takie same. Jeśli tak to strcmp zwróci wartość 0. Wtedy możemy wywołać odpowiednią funkcję. Linijki (8. - 12.) to przykładowe implementacje funkcji jednoargumentowych. (13.) Na sam koniec kończymy instrukcją break;, aby mieć pewność, że opuścimy instrukcje switch.

Zadania

Zadanie 1

Zmień linijkę kodu, aby liczbę dziesiętną można było wpisywać również przy pomocy przecinka ",".

Zadanie 2

Dodaj nowe funkcją abs, która będzie zwracać wartość absolutną podanej liczby.

* Zadanie 3

Dodaj nową funkcję delta, która dla danych wartości a, b, c obliczy wartość wyrażenia ∆ = b2 - 4ac. Zakładamy, że użytkownik na wejściu wprowadza je w kolejności a, b, c

Wskazówka: Na stosie liczby są w kolejności c, b, a