• Nie Znaleziono Wyników

Odrotna notacja polska

N/A
N/A
Protected

Academic year: 2021

Share "Odrotna notacja polska"

Copied!
39
0
0

Pełen tekst

(1)

Algorytmy i struktury danych

Algorytmy i struktury danych

Roman Simiński

roman.siminski@us.edu.pl roman@siminskionline.pl

programowanie.siminskionline.pl

Odwrotna notacja polska

Odwrotna notacja polska

Rozważania implementacyjne

Rozważania implementacyjne

(2)

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

2 2

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

2 2

( 2 + 3 ) * 5

( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * =

2 3 + 5 * =

Kierunek analizy wyrażenia

(3)

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

3 3

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

3 3

2

Połóż

( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

(4)

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

4 4

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

4 4

2

Połóż

( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

3

Liczba, kładziemy ją na stos

Liczba, kładziemy ją na stos

(5)

2

3

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

5 5

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

5 5 ( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

Stos

Operator, zdejmujemy jego argumenty

Operator, zdejmujemy jego argumenty

3

(6)

2

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

6 6

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

6 6 ( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

Stos

Operator, zdejmujemy jego argumenty

Operator, zdejmujemy jego argumenty

3

2

(7)

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

7 7

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

7 7 ( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

Stos

Operator, wartościujemy wyrażenie Operator, wartościujemy wyrażenie

3

2

+

5

(8)

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

8 8

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

8 8

Połóż

( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

Stos

Operator, wartość wyrażenia na stos

Operator, wartość wyrażenia na stos

3

2

+

55

(9)

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

9 9

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

9 9

Połóż

( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

Stos

5

Liczba, kładziemy ją na stosLiczba, kładziemy ją na stos

5

(10)

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

10 10

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

10 10 ( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

Stos

Operator, zdejmujemy jego argumenty

Operator, zdejmujemy jego argumenty

5

5

(11)

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

11 11

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

11 11 ( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

Stos

5

5

*

25

Operator, wartościujemy wyrażenie Operator, wartościujemy wyrażenie

(12)

25

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

12 12

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

12 12

Połóż

( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

Stos

5

5

*

25

Operator, wartość wyrażenia na stos

Operator, wartość wyrażenia na stos

(13)

25

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

13 13

Wyznaczanie wartości wyrażenia ONP, koncepcja

Wyznaczanie wartości wyrażenia ONP, koncepcja

13 13 ( 2 + 3 ) * 5 ( 2 + 3 ) * 5 2 3 + 5 * =2 3 + 5 * = 2 3 + 5 * =

Stos

Koniec wyrażenia, Wartość na stosie Koniec wyrażenia, Wartość na stosie

W tym algorytmie na stos trafiają argumenty, operatory nie

(14)

Wyznaczanie wartości

Wyznaczanie wartości

Wyrażenia ONP

Wyrażenia ONP

Pseudokod

Pseudokod

(15)

Wyznaczanie wartości wyrażenia ONP, pseudokod

Wyznaczanie wartości wyrażenia ONP, pseudokod

15 15

StosLiczbRzeczywistych stos; for( ; ; )

{

element = podajKolejnyElementWyrażenia( wyrazenieONP ); if( element == '=' )

break;

if( element jest liczbą ) stos.połóż( element ); else

{

// Element jest operatorem

double druga = stos.pobierz();

double pierwsza = stos.pobierz(); double wynik;

switch( element ) {

case '+' : wynik = pierwsza + druga; break; case '-' : wynik = pierwsza – druga; break; case '*' : wynik = pierwsza * druga; break; case '/' : wynik = pierwsza / druga; break; }

stos.połóż( wynik ); }

}

wypisz( "Wartość wyrażenia: " + stos.pobierz() );

Zakładamy, że wyrażenie jest poprawne

(16)

Wyznaczanie wartości

Wyznaczanie wartości

Wyrażenia ONP

Wyrażenia ONP

Przykład 1, C++

Przykład 1, C++

(17)

Wyznaczanie wartości wyrażenia ONP, przykład, C++

Wyznaczanie wartości wyrażenia ONP, przykład, C++

17 17 ((2+7)/3+(14-3)*4)/2 2 7 + 3 / 14 3 - 4 * + 2 / = ((2+7)/3+(14-3)*4)/2 2 7 + 3 / 14 3 - 4 * + 2 / =

Założenie:

Program wczytuje z stdin kolejne elementy wyrażenia zapisanego w ONP.

Każda wprowadzona linia zawiera liczbę lub operator.

Nie jest sprawdzana poprawność wyrażenia.

Wyrażenie musi być zakończone znakiem '='.

>2

>7

>+

>3

>/

>14

>3

>->4

>*

>+

>2

>/

>=

Wartosc wyrazenia: 23.5

ONP

(18)

Wyznaczanie wartości wyrażenia ONP, przykład, C++

Wyznaczanie wartości wyrażenia ONP, przykład, C++

18 18

if( sscanf( element, "%lf", &liczba ) == 1 )

Udane wyodrębnienie jednej liczby typu double (czyli long float) z łańcucha element i zapisanie do zmiennej liczba

else

Nieudane wyodrębnienie liczby

Do konwersji łańcuch znaków

→ liczba można wykorzystać funkcję sscanf.

Funkcja sscanf wyodrębnia elementy z łańcucha znaków będącego pierwszym

parametrem wywołania.

Wyodrębnianie odbywa się pod kontrolą parametrów zapisanych w drugim

parametrze.

Wydobyte informacje zapisywane są argumentach przekazywanych poprzez

wskaźniki.

Rezultatem jest liczba poprawnie wyodrębnionych elementów.

Funkcja sscanf ma zmienną liczbę parametrów.

(19)

Wyznaczanie wartości wyrażenia ONP, przykład, C++

Wyznaczanie wartości wyrażenia ONP, przykład, C++

19 19

const int MAKS_DL_LINII = 80;

Stack<double> stos; // Stos dla wczytywanych liczb

double liczba;

char linia[ MAKS_DL_LINII ]; for( ; ; )

{

// Wczytanie linii

cout << ">"; cin >> linia;

// Czy wczytano operator kończący wyrażenie

if( linia[ 0 ] == '=' ) break;

(20)

Wyznaczanie wartości wyrażenia ONP, przykład, C++

Wyznaczanie wartości wyrażenia ONP, przykład, C++

20 20

// Próba wydobycia z wczytanej linii wartości liczbowej

if( sscanf( linia, "%lf", &liczba ) == 1 ) stos.push( liczba );

else {

// Nie ma liczby, jest operator, zdejmujemy argumenty

double druga = stos.pop(); double pierwsza = stos.pop(); double wynik;

switch( linia[ 0 ] ) {

case '+' : wynik = pierwsza + druga; break;

case '-' : wynik = pierwsza - druga; break;

case '*' : wynik = pierwsza * druga; break;

case '/' : wynik = pierwsza / druga; break; } // Wynik na stos stos.push( wynik ); } }

(21)

Krok w stronę wyznaczania

Krok w stronę wyznaczania

wartości wyrażenia ONP

wartości wyrażenia ONP

C++

C++

(22)

Wydobycie elementów wyrażenia ONP, przykład C++

Wydobycie elementów wyrażenia ONP, przykład C++

22 22 2 7 + 3 / 14 3 - 4 * + 2 / = 2 7 + 3/ 14 3 -4 * + 2 / = 2 7+ 3 / 14 3 - 4 * + 2 / = 2 7 + 3 / 14 3 - 4 * + 2 / = 2 7 + 3/ 14 3 -4 * + 2 / = 2 7+ 3 / 14 3 - 4 * + 2 / =

Założenie:

Wyrażenie zapisane jest w łańcuchu znaków.

Elementy wyrażenia rozdzielone są separatorami – np. znakiem spacji.

Wyrażenie musi być zakończone znakiem '='.

(23)

Wydobycie elementów wyrażenia ONP, przykład C++

Wydobycie elementów wyrażenia ONP, przykład C++

23 23

void parsowanieWyrazeniaONP( char * wyrazenie ) {

// Tablica seperatorów rozdzielających elementy char separatory[] = " ";

// Wskaźnik będzie lokalizował kolejne elementy

char * element;

element = strtok( wyrazenie, separatory ); while( element != 0 )

{

// Przykładowe wykorzystanie znalezionego elementu

cout << endl << *element;

// Poszukiwanie następnego elementu

element = strtok( 0, separatory ); }

}

2 7 + ...

element

\0

Tu można dodać inne znaki separujące elementy

wyrażenia

Tu można dodać inne znaki separujące elementy

(24)

void parsowanieWyrazeniaONP( char * wyrazenie ) {

// Tablica seperatorów rozdzielających elementy char separatory[] = " ";

// Wskaźnik będzie lokalizował kolejne elementy

char * element;

element = strtok( wyrazenie, separatory ); while( element != 0 )

{

// Przykładowe wykorzystanie znalezionego elementu

cout << endl << *element;

// Poszukiwanie następnego elementu

element = strtok( 0, separatory ); }

}

Wydobycie elementów wyrażenia ONP, przykład C++

Wydobycie elementów wyrażenia ONP, przykład C++

24 24

2 \0 7 + ...

element

Pozycja startowa następnego wywołania

(25)

void parsowanieWyrazeniaONP( char * wyrazenie ) {

// Tablica seperatorów rozdzielających elementy char separatory[] = " ";

// Wskaźnik będzie lokalizował kolejne elementy

char * element;

element = strtok( wyrazenie, separatory ); while( element != 0 )

{

// Przykładowe wykorzystanie znalezionego elementu

cout << endl << *element;

// Poszukiwanie następnego elementu

element = strtok( 0, separatory ); }

}

Wydobycie elementów wyrażenia ONP, przykład C++

Wydobycie elementów wyrażenia ONP, przykład C++

25 25

2 \0 7 + ...

element

Pozycja startowa następnego wywołania

2

(26)

void parsowanieWyrazeniaONP( char * wyrazenie ) {

// Tablica seperatorów rozdzielających elementy char separatory[] = " ";

// Wskaźnik będzie lokalizował kolejne elementy

char * element;

element = strtok( wyrazenie, separatory ); while( element != 0 )

{

// Przykładowe wykorzystanie znalezionego elementu

cout << endl << *element;

// Poszukiwanie następnego elementu

element = strtok( 0, separatory ); }

}

Wydobycie elementów wyrażenia ONP, przykład C++

Wydobycie elementów wyrażenia ONP, przykład C++

26 26

2

2 \0 7 \0 + ...

element

Pozycja startowa następnego wywołania

(27)

void parsowanieWyrazeniaONP( char * wyrazenie ) {

// Tablica seperatorów rozdzielających elementy char separatory[] = " ";

// Wskaźnik będzie lokalizował kolejne elementy

char * element;

element = strtok( wyrazenie, separatory ); while( element != 0 )

{

// Przykładowe wykorzystanie znalezionego elementu

cout << endl << *element;

// Poszukiwanie następnego elementu

element = strtok( 0, separatory ); }

}

Wydobycie elementów wyrażenia ONP, przykład C++

Wydobycie elementów wyrażenia ONP, przykład C++

27 27

2

7

+

3

/

1

3

-4

*

+

2

/

=

2 \0 7 \0 + ... element \0

(28)

Wyznaczanie

Wyznaczanie

wartości wyrażenia ONP

wartości wyrażenia ONP

Funkcja C++

Funkcja C++

(29)

Wyznaczanie wartości wyrażenia ONP, funkcja, przykład, w C++

Wyznaczanie wartości wyrażenia ONP, funkcja, przykład, w C++

29 29

double wyliczWartoscWyrazeniaONP( char * wyrazenie ) {

Stack<double> stos;

char separatory[] = " "; char * element;

double liczba;

element = strtok( wyrazenie, separatory ); while( element != 0 )

{

if( *element == '=' ) break;

if( sscanf( element, "%lf", &liczba ) == 1 ) stos.push( liczba );

else . . .

std::cout << std::endl << wyliczWartoscWyrazeniaONP( "2 3 + 5 * =" );

Przykład wywołania:

(30)

Wyznaczanie wartości wyrażenia ONP, funkcja, przykład, C++

Wyznaczanie wartości wyrażenia ONP, funkcja, przykład, C++

30 30

. . . {

double druga = stos.pop(); double pierwsza = stos.pop(); double wynik;

switch( *element ) {

case '+' : wynik = pierwsza + druga; break;

case '-' : wynik = pierwsza - druga; break;

case '*' : wynik = pierwsza * druga; break;

case '/' : wynik = pierwsza / druga; break;

}

stos.push( wynik ); }

element = strtok( 0, separatory ); }

return stos.pop(); }

(31)

Konwersja wyrażenia do

Konwersja wyrażenia do

postaci ONP

postaci ONP

Pseudokod

Pseudokod

(32)

Konwersja wyrażenia do postaci ONP, algorytm

Konwersja wyrażenia do postaci ONP, algorytm

32 32

( ( 2 + 7 ) / 3 + ( 14 – 3 ) * 4 ) / 2 =

2 7 + 3 / 14 3 - 4 * + 2 / =

( ( 2 + 7 ) / 3 + ( 14 – 3 ) * 4 ) / 2 =

2 7 + 3 / 14 3 - 4 * + 2 / =

Założenie:

Wyrażenie zapisane jest w łańcuchu znaków.

Elementy wyrażenia rozdzielone są separatorami – np. znakiem spacji.

Wyrażenie musi być zakończone znakiem '='.

(33)

Konwersja wyrażenia do postaci ONP, algorytm iteracyjny

Konwersja wyrażenia do postaci ONP, algorytm iteracyjny

33 33

Wejście:

wyrażenie : łańcuch znaków onp : łańcuch znaków

StosOperatorow stos; for( ; ; )

{

element = podajKolejnyElementWyrażenia( wyrażenie ); if( koniec wyrażenia )

{

// Koniec wyrażenia źródłowego, pobierz operatory ze stosu, dopisz // je do wyrażenia ONP i zakończ działanie

while( !stos.empty() ) onp += stos.pop();

break; }

(34)

Konwersja wyrażenia do postaci ONP, algorytm iteracyjny

Konwersja wyrażenia do postaci ONP, algorytm iteracyjny

34 34

. . .

switch( element ) {

// Jeżeli odczytanym elementem jest nawias otwierający to należy po // odłożyć na stos

case '(' : stos.push( '(' ); break;

// Jeżeli odczytanym elementem jest nawias zamykający to należy pobrać // ze stosu wszystkie operatory aż do nawiasu otwierającego. Operatory // należy dopisać do wyrażenia ONP, nawias otwierający usunąć ze stosu

case ')' : while( stos.peek() != '(' )

onp += stos.pop(); // Pobranie operatora i dopisanie do ONP

stos.pop(); // Pobranie nawiasu otwierającego

break; . . .

(35)

Konwersja wyrażenia do postaci ONP, algorytm iteracyjny

Konwersja wyrażenia do postaci ONP, algorytm iteracyjny

. . .

// Odczytanym elementem jest operator, dopisujemy go do stosu, ale wcześniej // zdejmujemy operatory ze stosu i dopisujemy do wyrażenia ONP dopóki:

// odczytany operator ma łączność lewostronną oraz priorytet niższy // lub równy operatorowi na stosie

// lub

// operator ma łączność prawostronną oraz priorytet niższy od operatora // na stosie

case '+' : case '-' : case '*' :

case '/' : while( !stos.empty() ) {

// Wyskakujemy z iteracji jeżeli priorytet odczytanego operatora // (element) jest wyższy lub równy od operatora ze szczytu stosu

if( priorytet( element ) >= priorytet( stos.peek() ) ) break;

// Zdejmujemy operatory o wyższych priorytetach

onp += stos.pop(); }

stos.push( element ); break;

(36)

Konwersja wyrażenia do postaci ONP, algorytm iteracyjny

Konwersja wyrażenia do postaci ONP, algorytm iteracyjny

36 36

. . .

// Odczytanym elementem jest argument, dopisujemy go do wyrażenia ONP

default : onp += element; break;

}//switch

(37)

Konwersja wyrażenia do

Konwersja wyrażenia do

Postaci ONP

Postaci ONP

Funkcja w C++

Funkcja w C++

(38)

Konwersja wyrażenia do postaci ONP, przykład, C++

Konwersja wyrażenia do postaci ONP, przykład, C++

38 38

char * przeksztalcDoONP( char * wyrazenie, char * onp ) { Stack<char> stos; char separatory[] = " "; char * element; double liczba; char symbol; onp[ 0 ] = '\0';

element = strtok( wyrazenie, separatory ); while( element != 0 )

{

if( *element == '=' ) {

while( !stos.empty() )

dopiszZnak( onp, stos.pop() ); dopiszZnak( onp, '=' );

break; }

. . .

Funkcja pobiera wyrażenie w notacji infiksowej, zapisane w tablicy wyrazenie i buduje wyrażenie ONP, zapisując je do tablicy onp. Rezultatem funkcji jest tablica onp, fukcja akceptuje operatory + - * / = oraz argumenty w postaci liczb. Nie jest kontrolowane przepełnienie tablicy onp. Funkcja zakłada, że elementy wyrażenia źródłowego są rozdzielone znakami spacji.

Funkcja pobiera wyrażenie w notacji infiksowej, zapisane w tablicy wyrazenie i buduje wyrażenie ONP, zapisując je do tablicy onp. Rezultatem funkcji jest tablica onp, fukcja akceptuje operatory + - * / = oraz argumenty w postaci liczb. Nie jest kontrolowane przepełnienie tablicy onp. Funkcja zakłada, że elementy wyrażenia źródłowego są rozdzielone znakami spacji.

(39)

Konwersja wyrażenia do postaci ONP, przykład, C++

Konwersja wyrażenia do postaci ONP, przykład, C++

. . .

switch( *element ) {

case '(' : stos.push( '(' ); break;

case ')' : while( ( symbol = stos.pop() ) != '(' ) dopiszZnak( onp, symbol );

break; case '+' :

case '-' : case '*' :

case '/' : while( !stos.empty() ) {

if( priorytet( element ) >= priorytet( stos.peek() ) ) break;

dopiszZnak( onp, stos.pop() ); }

stos.push( *element ); break;

default : if( sscanf( element, "%lf", &liczba ) == 1 ) strcat( strcat( onp, element ), " " ); break;

}

element = strtok( 0, separatory ); // Pobranie następnego elementu wyrażenia

}

return onp; }

Rozważane tutaj operatory + - * / są lewostronnie łączne

Cytaty

Powiązane dokumenty

Miejsce to bowiem pozostawia dla Pana Boga, którego spotyka zarówno podczas intym ­ nych rozm ów na modlitwie, ja k i w czasie prozaicznych posług wobec bliźniego (s. Autor

[r]

Rowiński nie tylko fascynował się postę­ pem medycznym, ale był lekarzem w pełnym znaczeniu tego słowa; kreował on nowe wartości w. Następnie zabrała głos

[r]

O ile o che1nii, w przypadku zacierania się granic między orbi- talami, można jeszcze mówić.. Podobnie w 308 0g zacierają się powłoki neutronowe (lewy środkowy

W zakładce „Translate” z rozwijanego paska „Rule File” należy wybrać skompilowaną tablicę znaków: „polish_g1_new.ibk” i wprowadzić ją do programu WinBraille..

Napisz program, który w opcjach wyświetla menu, pozwala na wybór dowolnej czynności 3.1-3.3 i dowolna liczbę razy pozwala je powtórzyć oraz na Ŝądanie kończy

// utworzono tablicę 10 referencji typu String, naleŜy dla kaŜdego elementu tablicy przydzielić pamięć. • Przydział pamięci na elementy