rpn/rpncalc.c
/* Este programa simula uma calculadora RPN. O usu�rio deve
digitar uma express�o em nota��o RPN (nota��o polonesa);
o programa devolver� o valor da express�o. Cada linha
digitada deve conter um n�mero, um operador (+, -, *, /),
ou um dos seguintes comandos:
Q (quit): para sair do programa,
C (clear): para limpar a calculadora,
S (stack): para exibir o cont�udo da pilha.
Restri��es: cada linha deve ter no m�ximo 120 caracteres;
a pilha � limitada a 100 elementos (portanto, s� posso
garantir o funcionamento se a express�o tiver mais que
100 operandos.)
*/
/***************************************
* Se��o 1: Bibliotecas e tipos de dados
***************************************/
#include <stdio.h>
#include <stdlib.h> /* preciso de atof */
#include <ctype.h> /* preciso de isdigit, toupper etc. */
typedef char* string;
typedef enum {FALSE, TRUE} bool;
/************************************************************
* Se��o 2: Pilha (= stack)
* O programa armazena os resultados intermedi�rios em uma
* pilha de n�meros do tipo double. Essa estrutura est�
* sujeita a duas opera��es apenas:
* a opera��o empilha (= push) acrescenta um novo elemento
* ao topo da pilha;
* a opera��o desempilha (= pop) retira um elemento do topo
* da pilha.
************************************************************/
/* A pilha residir� no vetor stk[0..stkcount-1], sendo
stkcount - 1 o �ndice do tipo da pilha. As vari�veis
stk[] e stkcount ser�o globais.
*/
#define MaxStackSize 100
double stk[MaxStackSize];
int stkcount;
/* Opera��o "empilha": coloca element na pilha
stk[0..stkcount-1].
*/
void Push (double element)
{
if (stkcount == MaxStackSize) {
printf("Stack size exceeded.\n");
exit(EXIT_FAILURE);
}
stk[stkcount++] = element;
}
/* Opera��o "desempilha": retira o elementoque est�
no topo da pilha.
*/
double Pop (void)
{
if (stkcount == 0) {
printf("Pop of an empty stack.\n");
exit(EXIT_FAILURE);
}
return stk[--stkcount];
}
/***********************************
* Se��o 3: Prot�tipos de de fun��es
***********************************/
void ApplyOperator(char op);
void DisplayStack(void);
string getLine(void);
/*********************************************************
* Se��o 4: C�digo do programa de simula��o da calculadora
*********************************************************/
int main (void)
{
string line;
char ch;
printf("RPN Calculator Simulation\n");
stkcount = 0;
while (TRUE) {
printf("> ");
line = getLine();
ch = toupper(line[0]);
switch (ch) {
case 'Q': return 0;
case 'C': stkcount = 0; break;
case 'S': DisplayStack(); break;
default : if (isdigit(ch))
Push(atof(line));
else
ApplyOperator(ch);
break;
}
}
}
/* Esta fun��o aplica o operador op aos dois operandos que
est�o no topo da pilha stk[]. A fun��o sup�e que o
usu�rio n�o vai tentar divis�o por zero.
*/
void ApplyOperator(char op)
{
double lhs, rhs, result;
rhs = Pop(); /* operando direito */
lhs = Pop(); /* operando esquerdo */
switch (op) {
case '+': result = lhs + rhs; break;
case '-': result = lhs - rhs; break;
case '*': result = lhs * rhs; break;
case '/': result = lhs / rhs; break;
default : printf("Illegal operator\n");
exit(EXIT_FAILURE);
}
printf("%g\n", result);
Push(result);
}
/* Imprime o conte�do da pilha stk[0..stkcount-1].
*/
void DisplayStack(void)
{
int i;
printf("Stack: ");
if (stkcount == 0)
printf("empty\n");
else {
for (i = 0; i < stkcount; i++) {
if (i > 0) printf(", ");
printf("%g", stk[i]);
}
printf("\n");
}
}
/* L� uma linha do teclado e devolve a linha na forma de
uma string. A linha deve ter no m�ximo 100 caracteres.
Esta fun��o foi inspirada na GetLine da biblioteca
simpio de Eric Roberts, mas � bem mais simples que
aquela.
*/
string getLine(void)
{
string line;
int n, ch;
n = 0;
line = malloc(100+1);
if (line == NULL) {
printf("No memory available.\n");
exit(EXIT_FAILURE);
}
while ((ch = getc(stdin)) != '\n') {
if (n >= 100) {
free(line);
printf("Linha muito longa.\n");
exit(EXIT_FAILURE);
}
line[n++] = ch;
}
line[n] = '\0';
return line;
}