Calculadora RPN em C

por Fabio A. Mazzarino

Recentemente orientei um participante da lista ccppbrasil com um exercício que ele estava tentando fazer. E dentre as soluções que eu sugeri tinha a opção dele criar uma calculadora RPN utilizando C. Pra quem não sabe como funciona uma calculadora RPN (Notação Polonesa Reversa), pode dar uma olhada neste link.

Na verdade o rapaz queria fazer parse de álgebra direta, eu orientei fazer uma RPN com uma pilha de 2 variáveis, x e y. E agora eu desenvolvi a solução e decidi disponibilizar. Vamos a primeira opção:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
	char input[128] = "";
	int x = 0, y = 0;
	do {
		int ct = 0;
		printf("> ");
		scanf("%s", input);
		/* is digit? */
		for (ct = strlen(input); ct--; )
			if (!isdigit(input[ct]))
				break;
				
		if (ct < 0) {
			y = x;
			x = atoi(input);
			
		} else {
			if (strlen(input) > 1) {
				printf("\tInvalid operator: %s\n", input);
				continue;
			}
			switch (input[0]) {
				case '+':  x = y + x; break;
				case '-':  x = y - x; break;
				case '*':  x = y * x; break;
				case '/':  x = y / x; break;
				case 'q':  printf ("\tquit\n"); exit(0);
				default:  printf("\tInvalid operator: %s\n", input); continue;
			}
		}
		printf("\t%d\n", x);
							
	} while (input[0] != '\x0');
	exit(0);
}

Uma solução bem simples, utilizando conceitos básicos. Fica um desafio, fazer uma pilha de N elementos, ao invés de somente x e y. Outra opção é aceitar números negativos, ou de ponto flutuante.

Note a construção não ortodoxa do for para determinar se a entrada é numérica ou não. Para maiores informações veja neste post. Quando ct for negativo indica que o for percorreu todos os caracteres da string sem passar pelo break, ou seja, é exclusivamente numérico. Quando ct não for negativo indica que em algum momento o loop saiu através do break, signifiando que não é numérico.

Para a conversão para int eu usei a função atoi (ascii to int), é a forma mais simples de fazer parser de strings numéricas.

Quem quiser testar o código pode usar o arquivo disponibilizado no github.