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



Generated by GNU enscript 1.6.3.