01101101 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... #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; } else if( ch[ 0 ] == '=' ) { return false; } }
class MathFunctions { private: 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 ) 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; RPN.push( * it ); } else if(( * it ).TokenName == "," ) { cout << "Symbol: " <<( * it ).TokenName << endl; while( Stack.top().TokenName != "(" ) { RPN.push( Stack.top() ); Stack.pop(); } } else if(( * it ).IsOperator(( * it ).TokenName ) ) { cout << "Operator: " <<( * it ).TokenName << endl; 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; Stack.push( * it ); } else if(( * it ).TokenName == ")" ) { cout << "Bracket: " <<( * it ).TokenName << endl; 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] |
|
pekfos |
» 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_algorithmelse if the token is an operator then: while ((there is a operator at the top of the operator stack) |
else if(( * it ).IsOperator(( * it ).TokenName ) ) { cout << "Operator: " <<( * it ).TokenName << endl; 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. |
|
01101101 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 |
|
pekfos |
» 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. |
|
01101101 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ę ? queue < Token > RPN;
...
return RPN;
|
|
pekfos |
» 2020-08-25 18:33:21 Można. |
|
01101101 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. |
|
01101101 Temat założony przez niniejszego użytkownika |
» 2020-08-29 18:39:08 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] |
|
« 1 » 2 |