Calculadora com Notação Polonesa Reversa
Esta é a implementação de uma calculadora que funciona com Notação Polonesa Reversa. Ela é bastante simples, só funciona com inteiros e possui apenas as quatro operações aritméticas básicas, mas serve para mostrar como funciona. Para implementá-la, usei a biblioteca termios.h, especificada pelo padrão POSIX, então esse código provavelmente funciona em BSDs, Linux e Mac OS X. Não posso garantir que vá funcionar com o Windows, e o código só foi testado no Linux.
Para uma calculadora RPN 100% funcional, recomendo a galculator, em GTK+.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <termios.h> #define CTOI(x) (x-48) void silent(struct termios *init_setting, struct termios *new_setting); void verbose(struct termios *init_setting); void push_stack(int number, int *stack); void make_number(int *number, int new_digit); unsigned char get_char(void); int do_operation(int *number, int *stack, unsigned char operation); int main(int argc, char *argv[]) { struct termios init_setting, new_setting; unsigned char pressed = '', last = ''; int current_number = 0; int stack[3]; stack[0] = 0; stack[1] = 0; stack[2] = 0; printf("Basic RPN Calculator. Press 'q' to quit.\n"); silent(&init_setting, &new_setting); while(pressed != 'q') { last = pressed; pressed = get_char(); switch(pressed) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': verbose(&init_setting); write(fileno(stdin), &pressed, 1); if(last == '+' || last == '-' || last == '*' || last == '/') { push_stack(current_number, stack); current_number = CTOI(pressed); } else if(last == '\n') { current_number = CTOI(pressed); } else { make_number(¤t_number, CTOI(pressed)); } silent(&init_setting, &new_setting); break; case '\n': verbose(&init_setting); write(fileno(stdin), &pressed, 1); push_stack(current_number, stack); silent(&init_setting, &new_setting); break; case '+': case '-': case '*': case '/': verbose(&init_setting); printf("\n%c\t%d\n", pressed, do_operation(¤t_number, stack, pressed)); silent(&init_setting, &new_setting); break; default: break; } } verbose(&init_setting); return(0); } void silent(struct termios *init_setting, struct termios *new_setting) { tcgetattr(fileno(stdin), init_setting); new_setting = init_setting; new_setting->c_lflag &= ~(ICANON | ECHO | ISIG); new_setting->c_cc[VMIN] = 1; new_setting->c_cc[VTIME] = 0; tcsetattr(fileno(stdin), TCSADRAIN, new_setting); } void verbose(struct termios *init_setting) { tcsetattr(fileno(stdin), TCSADRAIN, init_setting); } void push_stack(int number, int *stack) { stack[2] = stack[1]; stack[1] = stack[0]; stack[0] = number; } void make_number(int *number, int new_digit) { *number = (*number*10) + new_digit; } unsigned char get_char() { unsigned char ch; read(fileno(stdin), &ch, sizeof(unsigned char)); return ch; } int do_operation(int *number, int *stack, unsigned char operation) { switch(operation) { case '+': *number = *number + stack[0]; break; case '-': *number = stack[0] - *number; break; case '*': *number = *number * stack[0]; break; case '/': *number = stack[0] / *number; break; } stack[0] = stack[1]; stack[1] = stack[2]; stack[2] = 0; return(*number); }
page_revision: 2, last_edited: 1238075588|%e %b %Y, %H:%M %Z (%O ago)





