Kalkulator ONP
Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Zarejestruj się!

Kalkulator ONP

AutorWiadomość
Temat założony przez niniejszego użytkownika
Kalkulator ONP
» 2020-08-20 16:15:49
Cześć, koduję właśnie kaklulator który używa Tokenizatora i Parsera. Utknąłem w miejscu pisania metody które konwertuje wyrażenie złożone z Tokenów na ostać ONP. Nie mogę się doszukać błędu w kodzie bo np dla takiego wyrażnia działa okej: (2+10) a dla 2+10 bez nawiasów juz się wywala na poziome operatora...

C/C++
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <stack>

using namespace std;

class Token
{
    friend class MathFunctions;
private:
    string TokenName;
    int priority;
    bool Operator;
    bool Number;
    bool Symbol;
public:
    int GetPriority( string ch );
    bool GetAssociative( string ch );
    bool IsOperator( string ch );
    bool IsNumber( string ch );
    bool IsVariable( string ch );
    bool IsFunction( string ch );
    bool IsSymbol( string ch );
    Token() { };
    Token( string Name, bool Ope, bool Num, bool Sym ) { TokenName = Name, Operator = Ope, Number = Num, Symbol = Sym; };
};

bool Token::IsNumber( string number_string )
{
    for( int i = 0; i < number_string.length(); i++ )
    {
        if( !isdigit( number_string[ i ] ) )
             return false;
       
    }
    return true;
}

bool Token::IsOperator( string ch )
{
    string operators = "+-*/";
    for( int i = 0; i < 4; i++ )
    {
        if( ch[ i ] == operators[ i ] ) //
             return true;
       
    }
    return false;
}

int Token::GetPriority( string ch )
{
    if( ch[ 0 ] == '+' || ch[ 0 ] == '-' )
    {
        priority = 1;
        return priority;
    } else if( ch[ 0 ] == '*' || ch[ 0 ] == '/' )
    {
        priority = 2;
        return priority;
    }
}

bool Token::GetAssociative( string ch )
{
    if( ch[ 0 ] == '+' || ch[ 0 ] == '*' || ch[ 0 ] == '-' || ch[ 0 ] == '/' )
    {
        return true; /// left
    }
    else if( ch[ 0 ] == '=' )
    {
        return false; /// right
    }
}

class MathFunctions
{
private:
    // vector<Token> ToRPN(vector <Token>);
public:
    MathFunctions(); //
    stack < Token > ToRPN( vector < Token > );
    int Parse( string exp );
    vector < Token > Tokenization( string exp );
    bool Calculator();
};

vector < Token > MathFunctions::Tokenization( string exp )
{
    int j;
    string tmp;
    vector < Token > tokens;
    for( int i = 0; i < exp.size(); i++ )
    {
        if( isdigit( exp[ i ] ) )
        {
            tmp = exp[ i ];
            j = i + 1;
            while( isdigit( exp[ j ] ) )
            {
                tmp += exp[ j ];
                j++;
            }
            cout << tmp << endl;
            Token tok( tmp, false, true, false );
            tokens.push_back( tok );
            i = j - 1;
        }
        else if( exp[ i ] == '+' || exp[ i ] == '-' || exp[ i ] == '*' || exp[ i ] == '/' )
        {
            cout << exp[ i ] << endl;
            tmp = exp[ i ];
            Token tok( tmp, true, false, false );
            tokens.push_back( tok );
        }
        else if( exp[ i ] == '(' || exp[ i ] == ')' )
        {
            tmp = exp[ i ];
            Token tok( tmp, false, false, true );
            tokens.push_back( tok );
        }
    }
    for( vector < Token >::iterator it = tokens.begin(); it != tokens.end(); ++it ) /// check
         cout << " " <<( * it ).TokenName;
   
   
    return tokens;
}


MathFunctions::MathFunctions()
{ }

stack < Token > MathFunctions::ToRPN( vector < Token > tok )
{
    stack < Token > RPN;
    stack < Token > Stack;
    cout << endl;
    for( vector < Token >::iterator it = tok.begin(); it != tok.end(); ++it )
    {
        if(( * it ).IsNumber(( * it ).TokenName ) )
        {
            cout << "Number: " <<( * it ).TokenName << endl; /// check
            RPN.push( * it );
        }
        else if(( * it ).TokenName == "," )
        {
            cout << "Symbol: " <<( * it ).TokenName << endl; /// check
            while( Stack.top().TokenName != "(" )
            {
                RPN.push( Stack.top() );
                Stack.pop();
            }
        }
        else if(( * it ).IsOperator(( * it ).TokenName ) )
        {
            cout << "Operator: " <<( * it ).TokenName << endl; /// check
           
            while( Stack.top().IsOperator( Stack.top().TokenName ) )
            {
                if((( * it ).GetAssociative(( * it ).TokenName ) && Stack.top().GetPriority( Stack.top().TokenName ) >=( * it ).GetPriority(( * it ).TokenName ) ) ||( !( * it ).GetAssociative(( * it ).TokenName ) && Stack.top().GetPriority( Stack.top().TokenName ) >( * it ).GetPriority(( * it ).TokenName ) ) )
                {
                    cout << "Operator na wyjscie " << endl;
                    RPN.push( Stack.top() );
                    Stack.pop();
                }
            }
            cout << "Operator na stos " << endl;
            Stack.push( * it );
        }
        else if(( * it ).TokenName == "(" )
        {
            cout << "Bracket: " <<( * it ).TokenName << endl; /// check
            Stack.push( * it );
        }
        else if(( * it ).TokenName == ")" )
        {
            cout << "Bracket: " <<( * it ).TokenName << endl; /// check
           
            while( Stack.top().TokenName != "(" )
            {
                if( Stack.top().IsOperator( Stack.top().TokenName ) )
                {
                    RPN.push( Stack.top() );
                    Stack.pop();
                }
            }
            Stack.pop();
        }
    }
    cout << "RPN : " << endl;
    while( !RPN.empty() )
    {
        cout << RPN.top().TokenName;
        RPN.pop();
    }
   
    cout << endl;
    cout << "Stack: " << endl;
    while( !Stack.empty() )
    {
        cout << Stack.top().TokenName;
        Stack.pop();
    }
   
    return RPN;
}


int main( int argc, char * argv[] )
{
    string exp;
    getline( cin, exp );
    vector < Token > tt;
    MathFunctions mt;
    tt = mt.Tokenization( exp );
    mt.ToRPN( tt );
   
    return 0;
}
[/i]
P-177454
» 2020-08-20 18:40:13
Strasznie wygląda ten twój kod.. trochę inżynierii wstecznej pomogło dość do paru szczegółów, które w sumie mogłeś podać od razu.
https://en.wikipedia.org/wiki​/Shunting-yard_algorithm
else if the token is an operator then:
    while ((there is a operator at the top of the operator stack)
C/C++
else if(( * it ).IsOperator(( * it ).TokenName ) )
{
    cout << "Operator: " <<( * it ).TokenName << endl; /// check
   
    while( Stack.top().IsOperator( Stack.top().TokenName ) )
    {
Po przepisaniu warunku pętli na C++, trzeba by najpierw sprawdzić, czy na stosie operatorów w ogóle coś jest, potem dopiero czy element na stosie spełnia własności.
P-177456
Temat założony przez niniejszego użytkownika
» 2020-08-22 17:50:13
Może zamiast stosu powinienem użyć kolejki w drugim przypadku w sensie przy RPN
P-177465
» 2020-08-22 21:36:44
Czyli już działa? Tam powinna być kolejka, stos w tym miejscu sprawi że wynik będzie wypisany wspak.
P-177467
Temat założony przez niniejszego użytkownika
» 2020-08-25 14:37:14
Działa ale nie dla wszystkich przypadków tak jak trzeba. Zastanawiam się czy można tak zwrócić kolejkę ?

C/C++
queue < Token > RPN;

...

return RPN;
P-177482
» 2020-08-25 18:33:21
Można.
P-177483
Temat założony przez niniejszego użytkownika
» 2020-08-28 14:49:56
Teraz wydaję wszystko działa jak należy, tylko muszę poprawić by działa też dla liczb ujemnych np - 2 bo tokenizator czyta to jako "-" czyli operator i dopiero "2" czyli liczba oraz dla liczb zmiennoprzecinkowych. Dzięki.
P-177484
Temat założony przez niniejszego użytkownika
» 2020-08-29 18:39:08
C/C++
bool Token::IsNumber( string number_string )
{
    double num = stod( number_string );
    for( int i = 0; i < number_string.length(); i++ )
    {
       
        if( !isdigit( number_string[ i ] ) )
             return false;
       
    }
    return true;
}

Wie ktoś dlaczego funkcja stod() nie chce działać? [/i]
P-177485
« 1 » 2
 Strona 1 z 2Następna strona