Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Znajdowanie wartości wyrażenia zapisanego w postaci ONP

Ostatnio zmodyfikowano 2015-02-11 14:13
Autor Wiadomość
do_matury
Temat założony przez niniejszego użytkownika
Znajdowanie wartości wyrażenia zapisanego w postaci ONP
» 2015-02-09 20:47:37
Witam,
podjąłem się realizacji podanego algorytmu, mianowicie obliczaniu wartości wyrażenia zapisanego w postaci Odwrotnej Notacji Polskiej.
Udało napisać mi się taki o to kod.
C/C++
#include <iostream>
#include <string>
using namespace std;
int oblicz( int a, int b, char znak )
{
    switch( znak )
    {
    case '*': return a * b;
    case '/': return a / b;
    case '+': return a + b;
    case '-': return a - b;
    case '^': int pow = a;
        for( int i = 1; i < b; i++ )
             pow *= a;
       
        return pow;
    }
}
int main()
{
    string dane;
    cout << "Podaj wyrazenie w notacji ONP: ";
    cin >> dane;
    int n;
    n = dane.length();
    int * tab = new int[ n ];
    int l = 0;
    for( int i = 0; i < n; i++ )
    {
        if( dane[ i ] == '*' || dane[ i ] == '/' || dane[ i ] == '+' || dane[ i ] == '-' || dane[ i ] == '^' )
        {
            tab[ l - 2 ] = oblicz( tab[ l - 2 ], tab[ l - 1 ], dane[ i ] );
            l--;
        }
        else
        {
            tab[ l ] = dane[ i ] - 48;
            l++;
        }
    }
    cout << tab[ 0 ];
}
Kod działa, przynajmniej dla wyrażeń które testowałem :)
Chodzi mi o to że w main przy konwersji z string na int muszę odejmować 48 ponieważ jeżeli tego nie zrobię wpisuje numery ASCII. Dało by się to zapisać w bardziej czytelny sposób? 
No i ten pierwszy warunek trochę jest rozbudowany, czy dało by się go zapisać w prostszy sposób?
Ale co najważniejsze, algorytm nie jest przystosowany do liczby dwucyfrowych i więcej ponieważ czyta pojedyncze znaki, a nie mam pomysłu jak to rozwiązać.
Oddzielać poszczególne wyrazy spacją? 
Z góry dziękuje za odpowiedź.
P-126273
darko202
» 2015-02-10 08:26:57
1. dokonaj konwersji przy pomocy funkcji stoi ewentualnie atoi
to rozwiąże też problem z jednym znakiem

http://www.cplusplus.com​/reference/string/stoi/
http://www.cplusplus.com​/reference/cstdlib/atoi/

2. rozbudowany warunek

stwórz funkcję zwracającą true/false podobną do funkcji oblicz
P-126284
Monika90
» 2015-02-10 11:06:47
Można wczytać całą linię za pomocą std::getline, a potem sparsować ją za pomocą std::istringstream, co może wyglądać tak:
C/C++
#include <iostream>
#include <string>
#include <sstream>

int main()
{
    std::cout << "Podaj wyrazenie w notacji ONP: ";
    std::string line;
    std::getline( std::cin, line );
    std::istringstream input( line );
    char ch;
    while( input >> ch )
    {
        if( ch >= '0' && ch <= '9' )
        {
            input.putback( ch );
            int number;
            input >> number;
            std::cout << "liczba: " << number << '\n';
        }
        else
             std::cout << "znak: " << ch << '\n';
       
    }
}
P-126288
do_matury
Temat założony przez niniejszego użytkownika
» 2015-02-11 14:13:43
Ok, dzięki za pomoc.
Zmieniłem warunek na ten który podała Monika90, niestety gdy chciałem użyć funkcji stoi, kompilator wyświetlał błąd, że funkcja stoi nie jest zainicjalizowana. Czytałem gdzieś że aby z niej skorzystać potrzebny jest standard C++11.
Rozwiązałem problem wczytania wieloznakowych operandów, przez dodanie funkcji który wczytuje kolejne znaki do napotkania spacji. Niestety wymaga to podczas wpisywania wyrażenia używania spacji po każdym elemencie wyrażenia nawet po symbolu operacji.
Sprawdzałem kod działa poprawnie.

C/C++
#include <iostream>
#include <string>
using namespace std;
int oblicz( int a, int b, char znak )
{
    switch( znak )
    {
    case '*': return a * b;
    case '/': return a / b;
    case '+': return a + b;
    case '-': return a - b;
    case '^': int pow = a;
        for( int i = 1; i < b; i++ )
             pow *= a;
       
        return pow;
    }
}
int czytaj( string s, int & i )
{
    int wynik = 0;
    while( s[ i ] != ' ' )
    {
        wynik = wynik * 10 +( s[ i ] - 48 );
        i++;
    }
    return wynik;
   
}
int main()
{
    string dane;
    char zn;
    cout << "+++++        Podaj wyrazenie w notacji ONP        +++++" << endl;
    cout << "UWAGA! Kazdy opernad i symbol dzialania oddziel spacja:" << endl;
    getline( cin, dane );
    int n;
    n = dane.length();
    int * tab = new int[ n ];
    int l = 0;
    for( int i = 0; i < n; i++ )
    {
        if( dane[ i ] >= '0' && dane[ i ] <= '9' )
        {
            tab[ l ] = czytaj( dane, i );
            l++;
        }
        else
        {
            tab[ l - 2 ] = oblicz( tab[ l - 2 ], tab[ l - 1 ], dane[ i ] );
            l--;
            i++;
        }
    }
    cout << tab[ 0 ];
}
[ cpp ]
P-126336
« 1 »
  Strona 1 z 1