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(&current_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(&current_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 tags: c rpn termios
page_revision: 2, last_edited: 1238075588|%e %b %Y, %H:%M %Z (%O ago)
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License