Rpcal - Uma simples calculadora RPN
Fiz uma calculadora muito simples, mas funcional que quero compartilhar para receber conselhos ou talvez criticas (não ofensivas, irônicas, sarcásticas ou inúteis. Como recebi em outros fóruns), para melhorar minhas habilidades. Devemos continuar aprendendo sempre. Ansiar sempre mais é da natureza humana e quando este anseio é benigno deve ser saciado.
Fiz em pouco tempo, por isso há alguns pontos que serão alterados, mas é relevante a sua opinião.
/*
* Copyright 2012 Mateus G. Pereira
*
* Este arquivo (stack.c) é parte do programa Rpcal
*
* Rpcal é um software livre; você pode redistribui-lo e/ou
* modifica-lo dentro dos termos da Licença Pública Geral GNU como
* publicada pela Fundação do Software Livre (FSF); na versão 2 da
* Licença, ou (na sua opnião) qualquer versão.
*
* Este programa é distribuido na esperança que possa ser util,
* mas SEM NENHUMA GARANTIA; sem uma garantia implicita de ADEQUAÇÂO
* a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. Veja a Licença
* Pública Geral GNU para maiores detalhes.
*
* Você deve ter recebido uma cópia da Licença Pública Geral GNU
* junto com este programa, se não, escreva para a Fundação do Software
* Livre(FSF) Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
*/
#include "stack.h"
#include <stdlib.h>
bool push (stack** st, TYPE elm)
{
stack* nstac;
nstac = (stack*) malloc( sizeof(stack) );
if(nstac == NULL)
return false;
nstac->element = elm;
nstac->last = *st;
*st = nstac;
return true;
}
TYPE pop (stack** st)
{
stack* aux;
TYPE elm;
if(*st == NULL)
return (TYPE)0;
elm = (*st)->element;
aux = (*st)->last;
free(*st);
*st = aux;
return elm;
}
TYPE top (stack* st)
{
if(st == NULL)
return (TYPE)0;
return st->element;
}
bool emp (stack* st)
{
return st == NULL;
}
/*
* Copyright 2012 Mateus G. Pereira
*
* Este arquivo (stack.h) é parte do programa Rpcal
*
* Rpcal é um software livre; você pode redistribui-lo e/ou
* modifica-lo dentro dos termos da Licença Pública Geral GNU como
* publicada pela Fundação do Software Livre (FSF); na versão 2 da
* Licença, ou (na sua opnião) qualquer versão.
*
* Este programa é distribuido na esperança que possa ser util,
* mas SEM NENHUMA GARANTIA; sem uma garantia implicita de ADEQUAÇÂO
* a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. Veja a Licença
* Pública Geral GNU para maiores detalhes.
*
* Você deve ter recebido uma cópia da Licença Pública Geral GNU
* junto com este programa, se não, escreva para a Fundação do Software
* Livre(FSF) Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
*/
#ifndef STACK_INCLUDED
#define STACK_INCLUDED
#define TYPE long double
typedef enum {false = 0, true = 1} bool;
typedef struct stack
{
TYPE element;
struct stack* last;
} stack;
bool push (stack**, TYPE);
TYPE pop (stack**);
TYPE top (stack*);
bool emp (stack*);
#endif
/*
* Copyright 2012 Mateus G. Pereira
*
* Este arquivo (tok.c) é parte do programa Rpcal
*
* Rpcal é um software livre; você pode redistribui-lo e/ou
* modifica-lo dentro dos termos da Licença Pública Geral GNU como
* publicada pela Fundação do Software Livre (FSF); na versão 2 da
* Licença, ou (na sua opnião) qualquer versão.
*
* Este programa é distribuido na esperança que possa ser util,
* mas SEM NENHUMA GARANTIA; sem uma garantia implicita de ADEQUAÇÂO
* a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. Veja a Licença
* Pública Geral GNU para maiores detalhes.
*
* Você deve ter recebido uma cópia da Licença Pública Geral GNU
* junto com este programa, se não, escreva para a Fundação do Software
* Livre(FSF) Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
*/
#include "tok.h"
#include <ctype.h>
#include <stdlib.h>
int strmatch (const char s, const char m)
{
while(*m != '\0')
if(*s++ != *m++)
return 0;
return 1;
}
void strnmake (char* s)
{
char* lk = s;
while(*lk != '\0')
{
if(!isspace(*lk))
*s++ = toupper((*lk == ',') ? '.':*lk);
lk++;
}
*s = '\0';
}
int strntk (char d, char str)
{
static char* s = NULL;
*d = '\0';
if(str != NULL)
s = str;
if(s == NULL)
return 0;
while(isspace(*s))
s++;
if(*s == '\0')
return 0;
while(!isspace(*s) && (*s != '\0'))
*d++ = *s++;
*d = '\0';
return 1;
}
/*
* Copyright 2012 Mateus G. Pereira
*
* Este arquivo (tok.h) é parte do programa Rpcal
*
* Rpcal é um software livre; você pode redistribui-lo e/ou
* modifica-lo dentro dos termos da Licença Pública Geral GNU como
* publicada pela Fundação do Software Livre (FSF); na versão 2 da
* Licença, ou (na sua opnião) qualquer versão.
*
* Este programa é distribuido na esperança que possa ser util,
* mas SEM NENHUMA GARANTIA; sem uma garantia implicita de ADEQUAÇÂO
* a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. Veja a Licença
* Pública Geral GNU para maiores detalhes.
*
* Você deve ter recebido uma cópia da Licença Pública Geral GNU
* junto com este programa, se não, escreva para a Fundação do Software
* Livre(FSF) Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
*/
#ifndef TOK_INCLUDED
#define TOK_INCLUDED
int strmatch (const char*, const char*);
int strntk (char*, char*);
void strnmake (char*);
#endif
/*
* Copyright 2012 Mateus G. Pereira
*
* Este arquivo (rpn.c) é parte do programa Rpcal
*
* Rpcal é um software livre; você pode redistribui-lo e/ou
* modifica-lo dentro dos termos da Licença Pública Geral GNU como
* publicada pela Fundação do Software Livre (FSF); na versão 2 da
* Licença, ou (na sua opnião) qualquer versão.
*
* Este programa é distribuido na esperança que possa ser util,
* mas SEM NENHUMA GARANTIA; sem uma garantia implicita de ADEQUAÇÂO
* a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. Veja a Licença
* Pública Geral GNU para maiores detalhes.
*
* Você deve ter recebido uma cópia da Licença Pública Geral GNU
* junto com este programa, se não, escreva para a Fundação do Software
* Livre(FSF) Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
*/
#include "rpn.h"
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
static stack* stk = NULL;
static TYPE res = 0;
bool rp_pop (TYPE* value)
{
if(emp(stk))
return false;
*value = pop(&stk);
return true;
}
TYPE rp_top ()
{
return top(stk);
}
bool rp_push (TYPE value)
{
return push(&stk, value);
}
void rp_free ()
{
res = 0;
while(!emp(stk))
pop(&stk);
}
TYPE rp_res ()
{
return res;
}
bool op_adc ()
{
TYPE lvalue, hvalue;
if(rp_pop(&lvalue))
{
if(rp_pop(&hvalue))
{
res = hvalue + lvalue;
return rp_push(res);
}
else
rp_push(lvalue);
}
return false;
}
bool op_sub ()
{
TYPE lvalue, hvalue;
if(rp_pop(&lvalue))
{
if(rp_pop(&hvalue))
{
res = hvalue - lvalue;
return rp_push(res);
}
else
rp_push(lvalue);
}
return false;
}
bool op_div ()
{
TYPE lvalue, hvalue;
if(rp_pop(&lvalue))
{
if(rp_pop(&hvalue))
{
res = hvalue / lvalue;
return rp_push(res);
}
else
rp_push(lvalue);
}
return false;
}
bool op_pow ()
{
TYPE lvalue, hvalue;
if(rp_pop(&lvalue))
{
if(rp_pop(&hvalue))
{
res = pow(hvalue, lvalue);
return rp_push(res);
}
else
rp_push(lvalue);
}
return false;
}
bool op_ln ()
{
TYPE lvalue;
if(rp_pop(&lvalue))
{
res = log(lvalue);
return rp_push(res);
}
return false;
}
bool op_log ()
{
TYPE lvalue;
if(rp_pop(&lvalue))
{
res = log10(lvalue);
return rp_push(res);
}
return false;
}
bool op_lg ()
{
TYPE lvalue;
if(rp_pop(&lvalue))
{
res = log2(lvalue);
return rp_push(res);
}
return false;
}
bool op_exp ()
{
TYPE lvalue;
if(rp_pop(&lvalue))
{
res = exp(lvalue);
return rp_push(res);
}
return false;
}
bool op_cos ()
{
TYPE lvalue;
if(rp_pop(&lvalue))
{
res = cos(lvalue);
return rp_push(res);
}
return false;
}
bool op_sen ()
{
TYPE lvalue;
if(rp_pop(&lvalue))
{
res = sin(lvalue);
return rp_push(res);
}
return false;
}
bool op_tan ()
{
TYPE lvalue;
if(rp_pop(&lvalue))
{
res = tan(lvalue);
return rp_push(res);
}
return false;
}
bool op_inv ()
{
TYPE lvalue;
if(rp_pop(&lvalue))
{
res = 1/lvalue;
return rp_push(res);
}
return false;
}
bool op_mul ()
{
TYPE lvalue, hvalue;
if(rp_pop(&lvalue))
{
if(rp_pop(&hvalue))
{
res = hvalue * lvalue;
return rp_push(res);
}
else
rp_push(lvalue);
}
return false;
}
/*
* Copyright 2012 Mateus G. Pereira
*
* Este arquivo (rpn.h) é parte do programa Rpcal
*
* Rpcal é um software livre; você pode redistribui-lo e/ou
* modifica-lo dentro dos termos da Licença Pública Geral GNU como
* publicada pela Fundação do Software Livre (FSF); na versão 2 da
* Licença, ou (na sua opnião) qualquer versão.
*
* Este programa é distribuido na esperança que possa ser util,
* mas SEM NENHUMA GARANTIA; sem uma garantia implicita de ADEQUAÇÂO
* a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. Veja a Licença
* Pública Geral GNU para maiores detalhes.
*
* Você deve ter recebido uma cópia da Licença Pública Geral GNU
* junto com este programa, se não, escreva para a Fundação do Software
* Livre(FSF) Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
*/
#ifndef RPN_INCLUDED
#define RPN_INCLUDED
#include "stack.h"
bool rp_push (TYPE);
bool rp_pop (TYPE*);
void rp_free ();
TYPE rp_top ();
TYPE rp_res ();
bool op_adc ();
bool op_sub ();
bool op_div ();
bool op_mul ();
bool op_cos ();
bool op_exp ();
bool op_lg ();
bool op_log ();
bool op_ln ();
bool op_pow ();
bool op_tan ();
bool op_sen ();
bool op_inv ();
#endif
/*
* Copyright 2012 Mateus G. Pereira
*
* Este arquivo é parte do programa Rpcal
*
* Rpcal é um software livre; você pode redistribui-lo e/ou
* modifica-lo dentro dos termos da Licença Pública Geral GNU como
* publicada pela Fundação do Software Livre (FSF); na versão 2 da
* Licença, ou (na sua opnião) qualquer versão.
*
* Este programa é distribuido na esperança que possa ser util,
* mas SEM NENHUMA GARANTIA; sem uma garantia implicita de ADEQUAÇÂO
* a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. Veja a Licença
* Pública Geral GNU para maiores detalhes.
*
* Você deve ter recebido uma cópia da Licença Pública Geral GNU
* junto com este programa, se não, escreva para a Fundação do Software
* Livre(FSF) Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "rpn.h"
#include "tok.h"
void rpnhelp()
{
puts("Calculadora simples utilizando o sistema lógico de Notação Polonesa Reversa\n" \
"\tajuda\tExibe este texto.\n" \
"\tsair\tFecha a calculadora.\n" \
"\tc\tLimpa a memoria.\n" \
"Funções disponiveis:\n" \
"\t+, -, *, /, ^, 1/x, log, lg, ln, exp, cos, sen, tan.\n" \
"Exemplos:\n" \
"\tAdição: 7 2 +\n" \
"\tSubtração: 3,5 2 -\n" \
"\tMultiplicação: 5,6 7,2 *\n" \
"\tDivisão: 9,23 12 /");
}
bool rpndo (const char* s)
{
bool nerror = false;
switch(*s)
{
case 'C':
if(*(s + 1) != 'O')
{
rp_free();
nerror = true;
}
break;
case '^':
nerror = op_pow();
break;
case '+':
nerror = op_adc();
break;
case '*':
nerror = op_mul();
break;
case '/':
nerror = op_div();
break;
case '-':
if(!isdigit(*(s + 1)) == true)
{
nerror = op_sub();
break;
}
default:
if(((isdigit(*s) || (*s == '-')) && (*(s + 1) != '/')) != false)
nerror = rp_push(strtod(s, NULL));
else if(((*(s + 1) == '/') && (*(s + 2) == 'X')) != false)
nerror = op_inv();
}
if(strmatch(s, "AJUDA") != false)
{
rpnhelp();
return true;
}
else if(strmatch(s, "LOG") != false)
nerror = op_log();
else if(strmatch(s, "LG") != false)
nerror = op_lg();
else if(strmatch(s, "LN") != false)
nerror = op_ln();
else if(strmatch(s, "EXP") != false)
nerror = op_exp();
else if(strmatch(s, "COS") != false)
nerror = op_cos();
else if(strmatch(s, "SEN") != false)
nerror = op_sen();
else if(strmatch(s, "TAN") != false)
nerror = op_tan();
else if(strmatch(s, "SAIR") != false)
return false;
if(nerror == false)
puts("Você forneceu dados insulficientes ou operadores invalidos.\n"
"Para mais informações digite: ajuda");
else
{
printf("^ %Lf\n", rp_top());
printf("= %Lf\n", rp_res());
}
return true;
}
bool rpnx (char* s)
{
bool cont;
char bfr[256];
cont = strntk(bfr, s);
while(cont != false)
{
strnmake(bfr);
if(!rpndo(bfr))
return false;
cont = strntk(bfr, NULL);
}
return true;
}
int main()
{
char line[256];
bool nquit;
puts("Rpcal 0.01 beta - Calculadora RPN\n" \
"Copyright 2012 Mateus G. Pereira\n");
do
{
fputs("->", stdout);
fgets(line, 256, stdin);
nquit = rpnx(line);
}
while(nquit);
rp_free();
return 0;
}
Quase esqueço de dizer que a inspiração para está calculadora surgiu do seguinte tópico: http://forum.imasters.com.br/topic/475682-calculadora-notacao-polonesa/page__view__findpost__p__1890154__fromsearch__1
Discussão (2)
Carregando comentários...