|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
[C++]Expr Algebriche
Sto provando a fare un parser di expr matematiche.
Ho creato la mia bella classina ma ho un problema Codice:
#include <list>
#include <string>
// The expression operator enum
typedef enum
{
PLUS = 0,
MINUS,
DIV,
MOD
} OpType;
// The Expression
struct ExprOp
{
OpType op;
std::string op1;
std::string op2;
ExprOp(const std::string &Op1, const std::string &Op2, OpType Op)
{
op1 = Op1;
op2 = Op2;
op = Op;
}
};
typedef std::list<ExprOp *> Expression;
typedef std::list<ExprOp *>::iterator Expression_it;
class CExprParse
{
private:
std::string ris;
Expression expr;
bool ParseEspr(const std::string &value);
public:
CExprParse();
~CExprParse();
CExprParse(CExprParse &p);
bool Exec();
inline const std::string Get();
bool addExpr(const std::string &value);
};
CExprParse::CExprParse()
{
}
CExprParse::CExprParse(CExprParse &p)
{
// no autoassignment
if(&p != this)
{
// TODO
}
}
CExprParse::~CExprParse()
{
}
bool CExprParse::ParseEspr(const std::string &value)
{
unsigned int plus_loc = value.find( "+", 0 );
unsigned int minus_loc = value.find( "-", 0 );
unsigned int div_loc = value.find( "/", 0 );
if(plus_loc != std::string::npos)
{
expr.push_back(new ExprOp(value.substr( 0, minus_loc ), value.substr( minus_loc, value.size() ),PLUS));
return true;
}
else if(minus_loc != std::string::npos)
{
expr.push_back(new ExprOp(value.substr( 0, minus_loc ), value.substr( minus_loc, value.size() ), MINUS));
return true;
}
else if(div_loc != std::string::npos)
{
expr.push_back(new ExprOp(value.substr( 0, minus_loc ), value.substr( minus_loc, value.size() ), DIV));
return true;
}else
{
return false;
}
}
bool CExprParse::addExpr(const std::string &value)
{
return (ParseEspr(value));
}
bool CExprParse::Exec()
{
std::string tmp("");
ExprOp * ex;
// IF EMPTY EXIT
if(expr.empty())
return false;
while(!expr.empty())
{
// RETURN THE PART OF EXRESSION TO EXECUTE
ex = expr.front();
//////////////////////////////////////////
///////// CHECK THE LITTERAL /////////////
//std::string f_l = ;
//std::string s_l = ;
/*
if(f_l == s_l) // ax + bx
{
switch(ex.op)
{
case PLUS:
break;
case MINUS:
break;
case DIV:
break;
}
}else // ax + by
{
switch(ex.op)
{
case PLUS:
break;
case MINUS:
break;
case DIV:
break;
}
}
*/
//////////////////////////////////////////
//////////CHECK THE NUMBERICAL ///////////
//int fist = static_cast< int >();
//int second = static_cast< int >();
//////////////////////////////////////////
////////// EXEC THE OPERARATION //////////
// REMOVE THE ELEMENT
expr.pop_front();
}
return true;
}
const std::string CExprParse::Get()
{
if(Exec())
return ris;
else
new std::string("Can't execute the expression\n");
}
La mia implementazione del metodo Exec va bene???? Tnk 10000000000000
__________________
Gnu/Linux User
|
|
|
|
|
|
#2 |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Non del tutto, non tanto per alcuni errori che ho notato qua e la' (quando prendi le sottostringhe ad esempio l'operazione finisce da une delle due parti), ma per l'approccio.
Per prima cosa ti interessa valutare singole operazioni (x+y o a/b ad esempio) o espressioni complete come a+b*c ? Mi sembra che la tua implementazione funzioni solo nel primo caso. Secondo me una cosa che potresti fare (ed e' quella che si fa di solito) e' quella di distinguere per prima cosa i numeri dalle operazioni, non andando a caccia delle operazioni, ma identificando gli elementi della espressione "da destra a sinistra", e creare degli oggetti (tokens) che li rappresentino. Da li' in poi procedere infine all'analisi vera e propria. Ad esempio potresti fare un oggetto del genere Codice:
enum token_type{ NUMBER , SUM , SUB , MUL , DIV };
struct Token
{
Token(token_type t):type(t){}
Token(int i):value(i){}
token_type type;
int value; // solo per il NUMBER
};
Codice:
template<class It>
vector<Token> lex( It begin , It end )
{
vector<Token> result;
while( begin != end )
{
"controlla cosa c'e' all'inizio dell'input"
switch( "tipo" )
{
case "numero":
result.push_back( Token(numero) );
break;
case '+':
result.push_back( Token(SUM) );
...
}
"Togli il valore appena trovato dall'input aggiornando 'begin'"
}
return result;
}
fatto questo ottieni una lista gia' un po' strutturata dell'input cosi' che ottieni qualcosa di indipendente dal numero di cifre e/o di spazi che hai, ti aiutera' inoltre ad individuare errori (cosa succede col tuo programa se scrivo "12 32 + 27" ?) |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
ho pensato di implementare meglio cosi:
Codice:
#include <list>
#include <string>
// The expression operator enum
typedef enum
{
PLUS = 0,
MINUS,
DIV,
MOD
} OpType;
// The Expression
struct ExprOp
{
OpType op;
std::string op1;
std::string op2;
ExprOp(const std::string &Op1, const std::string &Op2, OpType Op)
{
op1 = Op1;
op2 = Op2;
op = Op;
}
};
typedef std::list<ExprOp *> Expression;
typedef std::list<ExprOp *>::iterator Expression_it;
class CExprParse
{
private:
std::string ris;
Expression expr;
bool ParseEspr(const std::string &value);
public:
CExprParse();
~CExprParse();
CExprParse(CExprParse &p);
bool Exec();
inline const std::string Get();
bool addExpr(const std::string &value);
};
CExprParse::CExprParse()
{
}
CExprParse::CExprParse(CExprParse &p)
{
// no autoassignment
if(&p != this)
{
// TODO
}
}
CExprParse::~CExprParse()
{
}
bool CExprParse::ParseEspr(const std::string &value)
{
unsigned int plus_loc = value.find( "+", 0 );
unsigned int minus_loc = value.find( "-", 0 );
unsigned int div_loc = value.find( "/", 0 );
if(plus_loc != std::string::npos)
{
expr.push_back(new ExprOp(value.substr( 0, minus_loc ), value.substr( minus_loc, value.size() ),PLUS));
return true;
}
else if(minus_loc != std::string::npos)
{
expr.push_back(new ExprOp(value.substr( 0, minus_loc ), value.substr( minus_loc, value.size() ), MINUS));
return true;
}
else if(div_loc != std::string::npos)
{
expr.push_back(new ExprOp(value.substr( 0, minus_loc ), value.substr( minus_loc, value.size() ), DIV));
return true;
}else
{
return false;
}
}
bool CExprParse::addExpr(const std::string &value)
{
return (ParseEspr(value));
}
bool CExprParse::Exec()
{
std::string tmp("");
ExprOp * ex;
// IF EMPTY EXIT
if(expr.empty())
return false;
while(!expr.empty())
{
// RETURN THE PART OF EXRESSION TO EXECUTE
ex = expr.front();
unsigned int x_loc = ex->op1.find( "x", 0 );
unsigned int y_loc = ex->op1.find( "y", 0 );
unsigned int x2_loc = ex->op2.find( "x", 0 );
unsigned int y2_loc = ex->op2.find( "y", 0 );
if(x_loc != std::string::npos && x2_loc != std::string::npos) // ax + bx
{
/*
ax + bx
\
(a + b)x
\
abx
a = op1.substr(0, x_loc);
b = op2.substr(0, x2_loc);
*/
}
else if(x_loc != std::string::npos && y2_loc != std::string::npos) // ax + by
{
/*
ax + by
\
\
ax by
a = op1.substr(0, x_loc);
b = op2.substr(0, y2_loc);
*/
}
else if((x_loc == std::string::npos && y2_loc != std::string::npos)) // ay + by
{
/*
ay + by
\
(a + b)y
\
aby
a = op1.substr(0, y_loc);
b = op2.substr(0, y2_loc);
*/
}
expr.pop_front();
}
return true;
}
const std::string CExprParse::Get()
{
if(Exec())
return ris;
else
new std::string("Can't execute the expression\n");
}
Tnk
__________________
Gnu/Linux User
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Ma l'albero di derivazione non te lo sei costruito ?
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
volevo fare solo una prova x le addizioni con le liste.
Ho sbagliato???
__________________
Gnu/Linux User
|
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Se funziona va bene
Comunque studiati come costruire l'albero di derivazione... Fai 10 volte prima ad interpretare l'espressione... |
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
Quote:
Cmq se prova ad usare la classe mi termina immediatamente P.S: davvero va bene??
__________________
Gnu/Linux User
|
|
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
|
|
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
Quote:
Cmq nn sono molto esperto in fatto debug Qello del VC++ 6 va bene da usare???
__________________
Gnu/Linux User
|
|
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
|
|
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
Quote:
Pvt???
__________________
Gnu/Linux User
|
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
cmq questo è il cod finale:
Codice:
#include <list>
#include <string>
// The expression operator enum
typedef enum
{
PLUS = 0,
MINUS,
DIV,
MOD
} OpType;
// The Expression
struct ExprOp
{
OpType op;
std::string op1;
std::string op2;
ExprOp(const std::string &Op1, const std::string &Op2, OpType Op)
{
op1 = Op1;
op2 = Op2;
op = Op;
}
};
typedef std::list<ExprOp *> Expression;
typedef std::list<ExprOp *>::iterator Expression_it;
//////////////////////////////////////////////////////////////////////////
// The Expression Class //
//////////////////////////////////////////////////////////////////////////
class CExprParse
{
private:
std::string ris;
Expression expr;
bool ParseEspr(const std::string &value);
public:
CExprParse();
~CExprParse();
bool Exec();
inline const std::string Get();
bool addExpr(const std::string &value);
};
CExprParse::CExprParse()
{
ris = "";
}
CExprParse::~CExprParse()
{
}
bool CExprParse::ParseEspr(const std::string &value)
{
unsigned int plus_loc = value.find( "+", 0 );
unsigned int minus_loc = value.find( "-", 0 );
unsigned int div_loc = value.find( "/", 0 );
if(plus_loc != std::string::npos)
{
expr.push_back(new ExprOp(value.substr( 0, minus_loc ), value.substr( minus_loc, value.size() ),PLUS));
return true;
}
else if(minus_loc != std::string::npos)
{
expr.push_back(new ExprOp(value.substr( 0, minus_loc ), value.substr( minus_loc, value.size() ), MINUS));
return true;
}
else if(div_loc != std::string::npos)
{
expr.push_back(new ExprOp(value.substr( 0, minus_loc ), value.substr( minus_loc, value.size() ), DIV));
return true;
}else
{
return false;
}
}
bool CExprParse::addExpr(const std::string &value)
{
return (ParseEspr(value));
}
bool CExprParse::Exec()
{
// THIS FUNCTION MAKE ONLY PLUS OPERATION
ExprOp * ex;
// IF EMPTY EXIT
if(expr.empty())
return false;
unsigned int
x_loc,
y_loc,
x2_loc,
y2_loc;
while(!expr.empty())
{
// RETURN THE PART OF EXRESSION TO EXECUTE
ex = expr.front();
x_loc = ex->op1.find( "x", 0 );
y_loc = ex->op1.find( "y", 0 );
x2_loc = ex->op2.find( "x", 0 );
y2_loc = ex->op2.find( "y", 0 );
if(x_loc != std::string::npos && x2_loc != std::string::npos) // ax + bx
{
/*
ax + bx
\
(a + b)x
\
abx
a = op1.substr(0, x_loc);
b = op2.substr(0, x2_loc);
*/
std::string
a_s = ex->op1.substr(0, x_loc),
b_s = ex->op2.substr(0, x2_loc);
const char
* a = a_s.c_str(),
* b = b_s.c_str();
int tot = (int)a + (int)b;
ris += tot;
ris += "x";
}
else if(x_loc != std::string::npos && y2_loc != std::string::npos) // ax + by
{
/*
ax + by
\
\
ax by
a = op1.substr(0, x_loc);
b = op2.substr(0, y2_loc);
*/
ris += ex->op1;
ris += ex->op2;
}
else if((y_loc != std::string::npos && y2_loc != std::string::npos)) // ay + by
{
/*
ay + by
\
(a + b)y
\
aby
a = op1.substr(0, y_loc);
b = op2.substr(0, y2_loc);
*/
std::string
a_s = ex->op1.substr(0, y_loc),
b_s = ex->op2.substr(0, y2_loc);
const char * a = a_s.c_str(), * b = b_s.c_str();
int tot = (int)a + (int)b;
ris += tot;
ris += "y";
}
expr.pop_front();
}
return true;
}
const std::string CExprParse::Get()
{
if(Exec())
return ris;
else
new std::string("Can't execute the expression\n");
}
__________________
Gnu/Linux User
|
|
|
|
|
|
#13 |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Codice:
if(plus_loc != std::string::npos)
{
expr.push_back(new ExprOp(value.substr( 0, minus_loc ), value.substr( minus_loc, value.size() ),PLUS));
return true;
}
|
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
Quote:
__________________
Gnu/Linux User
|
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
Ora mia da errore
__________________
Gnu/Linux User
|
|
|
|
|
|
#16 |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
eh, dove ?
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
no anzi.
Risolto. Tnk Per i nomi ................. come dovrei chiamarle le var??? Mentre l'ordine è ok, no?
__________________
Gnu/Linux User
|
|
|
|
|
|
#18 |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
un nome tale che se riguardi il codice dopo una settimana che non lo tocchi capisci ancora cosa fa
|
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Apr 2002
Città: Vigevano(PV)
Messaggi: 2124
|
ora mi da il ris in athac..................why?
__________________
Gnu/Linux User
|
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Debug debug debug
F9 per emttere i break point F5 per far girare il programma in debug (l'esecuzione si ferma sui break point) F11 e F10 per andare passo-passo Aggiungi i watch (scrivi il nome della variabile o l'espressione da valutare)... |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 04:42.



















