PDA

Visualizza la versione completa : [C++] Calcolo funzione / espressione da me inserita


Enryx
28-12-2012, 12:47
Ciao a tutti,
Studio informatica da autodidatta da circa un anno, un mio amico mi ha detto di provare a fare un programma dove:
1) Inserisco una funzione da tastiera
2) il programma deve controllare se la funzione corretta (non ci siano errori di sintassi)
3) deve calcolarla in tutto il suo dominio.

Pensavo di andare a inserire la mia funzione in una stringa, ma ora non so pi andare avanti..suggerimenti?

Grazie :)


template <class ITEM> class EQUAZIONE; // forward

template <class ITEM> struct frame {
struct Campo {
float numero;
char variabile;
};
EQUAZIONE<ITEM> coda;
};

template <class ITEM> class EQUAZIONE {
private:
typedef frame<ITEM>* link;
link sp; // puntatore a nuova istanza di EQUAZIONE
public:
EQUAZIONE<ITEM> () { // costruttore senza parametri: inizializza l'oogetto come pila vuota
sp=NULL;
}
bool Verifica_carattere_inserito (char funzione[], int cont) { // Questo metodo verifica che i caratteri inseriti all'utente siano ammessi
bool r;
for(int a=0;a<cont-1;a++) {
if( ( (funzione[a]>=40)&&(funzione[a]<=57) ) && (funzione[a]==94) )
r=true;
else
r=false;
}
return r;
}
void Tipo_carattere (char funzione[], int cont) { // Questo metodo stabilisce se il carattere inserito, dopo essere sicuro che sia lecito, stabilisce se un numero o un operatore
link a = new frame<ITEM>;
for(int b=0;b<cont-1;b++) {
if( (funzione[b]>=48)&&(funzione[b]<=57) ) { // 48 = codice ASCII 0 , 57 = codice ASCII 9
a->Campo.numero = funzione[b];
a->Campo.variabile = NULL;
a->coda.sp = sp;
sp = a;
}
if( ( (funzione[b]>=40)&&(funzione[b]<=47) || (funzione[b]==94) ) ) { // 40 = codice ASCII ( , 47 = codice ASCII / , 94 = codice ASCII ^
a->Campo.numero = NULL;
a->Campo.variabile = funzione[b];
a->coda.sp = sp;
sp = a;
}
}
return true;
}
/* void print () const {
if (sp != NULL) {
sp->coda.print(); // qui applicato ricorsivamente questo metodo ...
sp->numero.print(); // ... ma qui applicato il metodo della classe ITEM!
sp->variabile.print();
}
}
*/
};

// Ordine di applicazione metodi classe:
// 1) Verifica_carattere_inserito
// 2) TIpo_carattere

void wait ( int seconds ) {
clock_t endwait;
endwait = clock () + seconds * CLK_TCK ;
while (clock() < endwait) {}
}
void conta () {
int i=1;
do {
printf(".");
wait( 1 );
i++;
}
while(i<=3);
}

int _tmain()
{
char funzione[50],c;
int cont=0,i=1;
EQUAZIONE <char> E1;

// Inseririmento funzione (funziona!)
printf("Inserire una funzione (per terminare la lettura della stessa inserire =):\n");
scanf("%c", &c);
funzione[0]=c;
while(c!=61) {
scanf("%c", &c);
funzione[i]=c;
cont++;
i++;
}
printf("\n\n");
printf("Sto analizzando la funzione");
conta();
printf("\n\n");

// Verifica della correttezza della funzione inserita (funziona!)
if(E1.Verifica_carattere_inserito(funzione,cont))
printf("La funzione inserita contiene tutti caratteri corretti!");
else
printf("La funzione non e' stata inserita in maniera corretta!");

// Determinazione della composizione dell'equazioni
// E1.print();
getch();
return 0;
}

MItaly
28-12-2012, 14:03
Quello che stai cercando di costruire un parser di espressioni, documentati in rete, c' un sacco di materiale in proposito; in particolare, per i tuoi scopi potrebbe andare bene un parser a discesa ricorsiva (recursive descent parser), relativamente semplice da implementare e dal funzionamento chiaro.

Un appunto al volo sul codice: quando scrivi cose di questo genere:

if( (funzione[b]>=48)&&(funzione[b]<=57) ) { // 48 = codice ASCII 0 , 57 = codice ASCII 9
puoi pi semplicemente scrivere


if( (funzione[b]>='0')&&(funzione[b]<='9') ) {
che ha il vantaggio di essere portabile e pi chiara, o anche meglio,


if(isnum(funzione[b])) {
con isnum dall'header <cctype>.

Per inciso, il linguaggio di riferimento va specificato nel titolo come "tag", qui aggiusto io.

Enryx
02-01-2013, 12:00
Ciao,
Mi sono un po' informato come mi hai detto, in pratica devo costruire un grafo, ma non ho assulutamente capito come fare :dh:
Grazie per l'appunto sul codice, non sapevo si potesse fare!

MItaly
02-01-2013, 18:17
Non strettamente necessario costruire un AST, puoi anche semplicemente valutare l'espressione "mentre" effettui il parsing; ad esempio, puoi dare un'occhiata a questo (http://www.speqmath.com/tutorials/expression_parser_cpp/index.html), il codice relativamente semplice da capire (anche se alcune scelte di interfaccia sono discutibili, vedi questa (http://forum.html.it/forum/showthread.php?s=&threadid=1525527) discussione, in cui tra l'altro trovi anche il codice completo di un altro parser di espressioni).

Se invece vuoi una libreria pi potente, puoi dare un'occhiata qui (http://www.codeproject.com/Articles/7773/Fast-Mathematical-Expressions-Parser) (effettua il parsing e traduce in bytecode con qualche ottimizzazione, cos che ri-valutare la stessa espressione con parametri differenti sia estremamente efficiente).

Enryx
03-01-2013, 11:41
MItaly ho guardato quello che mi hai linkato, per non riesco a capire.
Come faccio a implementare un parser al mio codice?
Questa roba qu mi proprio sconosciuta :confused:

oregon
03-01-2013, 11:44
Originariamente inviato da Enryx
Questa roba qu mi proprio sconosciuta :confused:

Probabilmente il compito che ti ha indicato il tuo amico pi complesso di quello che credevi.

Enryx
04-01-2013, 12:31
Ho paura pure io.
Mi sa che per il momento allora abbandono il progetto!
Se qualcuno ha voglia e tempo di mettersi a farlo e commentarlo (in modo che riesca a capirlo) nessun problema :D

Loading