Ciao Lalaith,

il seguente programma effettua l'analisi lessicale di una stringa contenente un'espressione e ne restituisce il risultato:

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;
}
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.