Ciao Lalaith,
il seguente programma effettua l'analisi lessicale di una stringa contenente un'espressione e ne restituisce il risultato:
Praticamente leggiamo l'input un carattere alla volta e lo suddividiamo nei vari componenti (token): numeri, operatori, parentesi. La tecnica utilizzata per valutare l'espressione è detta a discesa ricorsiva perchè utilizza una serie di procedure che si richiamo ricorsivamente a vicenda.codice:#include <stdlib.h> #include <ctype.h> #include <stdio.h> #include <string.h> #define DELIMITATORE 1 #define NUMERO 2 char *Espressione; char token[80]; char token_type; void ValutaEspressione(double *risultato); void AddizioneSottrazione(double *risultato); void MoltiplicazioneDivisione(double *risultato); void Esponente(double *risultato); void Unario(double *risultato); void Parentesi(double *risultato); void Valore(double *risultato); void get_token(void); void token_back(void); void Errore(int error); int isdelim(char c); void ValutaEspressione(double *risultato) { get_token(); if(!*token) { Errore(2); return; } AddizioneSottrazione(risultato); if( *token ) Errore(0); } void AddizioneSottrazione(double *risultato) { register char op; double temp; MoltiplicazioneDivisione(risultato); while((op = *token) == '+' || op == '-') { get_token(); MoltiplicazioneDivisione(&temp); switch(op) { case '-': *risultato = *risultato - temp; break; case '+': *risultato = *risultato + temp; break; } } } void MoltiplicazioneDivisione(double *risultato) { register char op; double temp; Esponente(risultato); while((op = *token) == '*' || op == '/' || op == '%') { get_token(); Esponente(&temp); switch(op) { case '*': *risultato = *risultato * temp; break; case '/': if(temp == 0.0) { Errore(3); /* divisione per zero */ *risultato = 0.0; } else *risultato = *risultato / temp; break; case '%': *risultato = (int) *risultato % (int) temp; break; } } } void Esponente(double *risultato) { double temp, ex; register int t; Unario(risultato); if( *token == '^' ) { get_token(); Esponente(&temp); ex = *risultato; if(temp==0.0) { *risultato = 1.0; return; } for( t=temp-1; t>0; --t ) *risultato = (*risultato) * (double)ex; } } void Unario(double *risultato) { register char op; op = 0; if( (token_type == DELIMITATORE) && *token=='+' || *token == '-' ) { op = *token; get_token(); } Parentesi(risultato); if( op == '-' ) *risultato = -(*risultato); } void Parentesi(double *risultato) { if( (*token == '(') ) { get_token(); AddizioneSottrazione(risultato); if(*token != ')') Errore(1); get_token(); } else Valore(risultato); } void Valore(double *risultato) { if( token_type == NUMERO ) { *risultato = atof(token); get_token(); return; } Errore(0); /* C'è un errore nell'espressione */ } void token_back(void) { char *t; t = token; for(; *t; t++) Espressione--; } void Errore(int error) { static char *e[]= { "Errore di sintassi", "Parentesi non bilanciate", "Nessuna espressione", "Divisione per zero", "Input errato" }; printf("%s\n", e[error]); } /* Ritorna il token successivo. */ void get_token(void) { register char *temp; token_type = 0; temp = token; *temp = '\0'; if( !*Espressione ) return; while( isspace(*Espressione)) ++Espressione; /* saltiamo gli spazi bianchi */ if( strchr("+-*/%^=()", *Espressione) ) { token_type = DELIMITATORE; *temp++ = *Espressione++; } else if( isalpha(*Espressione) ) { Errore(4); } else if( isdigit(*Espressione) ) { while( !isdelim(*Espressione) ) *temp++ = *Espressione++; token_type = NUMERO; } *temp = '\0'; } int isdelim(char c) { if( strchr(" +-/*%^=()", c) || c == 0 || c == '\r' || c == 9 ) return 1; return 0; } int main(void) { double risultato; char *p; p = (char *) malloc(256); if(!p) { printf("Errore nell'allocazione di memoria.\n"); return -1; } do { Espressione = p; printf("Inserisci un'espressione: "); gets(Espressione); if(!*Espressione) break; ValutaEspressione(&risultato); printf("Il risultato e': %.2f\n", risultato); } while(*p); /* Cicla finchè non viene inserita una stringa vuota */ if ( p ) free(p); return 0; }

Rispondi quotando