![]() |
|
|
|
|
Por vezes existe a necessidade de calcular expressões matemáticas que utilizam vários operadores e com recurso a parêntesis para alterar a ordem dos cálculos dentro da expressão. Devido aos diferentes níveis de prioridade dos operadores, não é muito fácil de fazer um programa que calcula uma expressão por muito simples que ela seja.
O algoritmo apresentado aqui tem a vantagem de ser rápido comparado com muitos que tenho utilizado e de ser facilmente expansível ao numero de operadores que se quiser.
Este primeiro algoritmo é o mais simples e é utilizado para o calculo de uma expressão matemática que contenha números reais, os quatro operadores básicos (+ - x /) e parêntesis. Nesta primeira versão não são utilizadas variáveis.
Para compreendermos o algoritmo necessitamos primeiro de analisar como é composta uma expressão matemática.
Uma expressão matemática é toda a expressão que contenha números, operadores e parêntesis. Cada expressão pode por sua vez ser composta por termos, que são sub-expressões separadas pelos operadores de + ou -. Por ultimo temos os factores que são sub-termos separados pelos operadores de x e /. Um termo pode ser: um numero ou uma expressão contida entre parêntesis que poderá ser dividida novamente em termos e factores.
A figura seguinte ilustra melhor o que foi descrito.

Figura P.1 - Diagrama da constituição de uma expressão matemática
Esta subdivisão termina quando todos os factores forem números. Esta técnica de analisar as expressões matemáticas permite que se utilize recursividade num programa em C que tenha como objectivo calcular o resultado final da expressão.
Antes de continuarmos acho melhor pôr em evidência um aspecto que pode vir a fazer alguma confusão na discussão seguinte.
Quando se fala em recursividade é natural que se pense num programa que contém uma função que se chama a ela própria pelo menos uma vez. Esta é a chamada recursividade directa. Outro tipo de recursividade é a indirecta que utiliza mais de uma função. Suponhamos que temos um programa que utiliza recursividade directa, neste caso algures no corpo do programa teremos a função recursiva.
No caso da recursividade indirecta e para três funções temos o seguinte exemplo de código:
Este ultimo tipo de recursividade é o ideal para o tipo de analise de realizamos anteriormente nas expressões.
O algoritmo utiliza a recursividade indirecta através de três funções: expressão, termo e factor. A função expressão (a primeira a ser chamada), chama a função termo que por sua vez chama a função factor. Se o factor for constituído por sub-expressões, a função expressao é novamente chamada.
O algoritmo vai ser agora aplicado a um programa que mais não é do que uma calculadora de linha de comando.
A função matemática é introduzida num array de caracteres exp, tendo esse array o máximo de 30 posições o que nos possibilita calcularmos uma expressão de 29 caracteres.
Para evitar passar argumentos nas funções recursivas é utilizado um ponteiro global a que vai percorrer todo o array exp durante a execução das funções recursivas.
Figura P.2 - Relacionamento entre o ponteiro a e o array exp
Como mostra a figura anterior, o ponteiro a é inicializado com o valor do array exp.
char *a; // ponteiro global para o array de caracteres
Na função main é chamada pela primeira vez a função expressão que devolve o resultado final.
void main ()
{
char exp[30];
fflush (stdin); //limpa o buffer do teclado
while (printf("\nExpressão ('sair' para terminar): "),strcmp(gets (exp),"sair"))
{
a=exp;//inicializa o ponteiro 'a'
printf ("\nResultado: %lf\n",expressao());
fflush (stdin);
}
}
A função expressao subdivide a expressão em vários termos que estão separados pelos operadores + ou -.
double expressao ()
{
double z;
short n=1;
z=termo ();
while (n)
switch (*a)
{
case '+':a++;
z+=termo ();
break;
case '-':a++;
z-=termo ();
break;
default :n=0;
}
return z;
}
A função termo subdivide a expressão em vários factores que estão separados pelos operadores x ou /.
double termo ()
{
double z,aux;
short n=1;
z=factor();
while (n)
switch (*a)
{
case '*':a++;
z*=factor();
break;
case '/':a++;
z/=factor();
break;
default: n=0;
}
return z;
}
Finalmente a função factor devolve o valor do factor (caso este seja um numero) ou chama novamente a função expressao (no caso do factor ser uma nova expressão). Neste ultimo caso terá obrigatoriamente de começar por parêntesis.
double factor ()
{
double z;
int i;
if (isdigit(*a))
{
for (i=1;isnum(*(a+i));i++);
z=atof(a);
a+=i;
}
else
if (*a=='-') //se o numero for negativo...
{
a++;
z=factor ()*(-1.0); //... é chamado novamente o factor e multiplicado
por -1
}
else
if (*a=='(')
{
a++;
z=expressao ();
a++;
}
return z;
}
Para fazer o download do código e do executável, clique aqui.
|
Comentários ou críticas podem ser enviados para hcsoftware@mail.pt
Ultima actualização: 30 Setembro 2000 |