kalkulacka
This commit is contained in:
parent
150fccfddc
commit
28a85c8514
18
sk2/Makefile
Normal file
18
sk2/Makefile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
CC=gcc
|
||||||
|
CFLAGS=-std=c11 -Wall -Wextra -O2
|
||||||
|
LDFLAGS=-lm
|
||||||
|
|
||||||
|
all: calc
|
||||||
|
|
||||||
|
calc: main.o calculator.o
|
||||||
|
$(CC) $(CFLAGS) -o calc main.o calculator.o $(LDFLAGS)
|
||||||
|
|
||||||
|
main.o: main.c calculator.h
|
||||||
|
$(CC) $(CFLAGS) -c main.c
|
||||||
|
|
||||||
|
calculator.o: calculator.c calculator.h
|
||||||
|
$(CC) $(CFLAGS) -c calculator.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o calc
|
||||||
|
|
||||||
59
sk2/README.MD
Normal file
59
sk2/README.MD
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Vedecká kalkulačka Matej Hajduk
|
||||||
|
|
||||||
|
## Zadanie
|
||||||
|
Naprogramovať vedeckú kalkulačku, ktorá vyhodnocuje matematické výrazy v infixnej notácii.
|
||||||
|
Kalkulačka musí podporovať:
|
||||||
|
|
||||||
|
- načítanie a prácu s číslami s presnosťou min. 2 desatinné miesta
|
||||||
|
- sčítanie, odčítanie, násobenie, delenie
|
||||||
|
-zátvorky
|
||||||
|
- funkcie: sinus, cosinus, odmocnina, druhá mocnina, logaritmus
|
||||||
|
|
||||||
|
Príklad:
|
||||||
|
- (2 + 3) * 2 -> 10
|
||||||
|
- (10 * 2) + (6 / 2) -> 23
|
||||||
|
|
||||||
|
|
||||||
|
## Stručný opis funkčnosti
|
||||||
|
Program číta matematické výrazy zo štandardného vstupu (každý výraz na samostatnom riadku).
|
||||||
|
Pre každý výraz vypočíta výsledok a vypíše ho na štandardný výstup.
|
||||||
|
|
||||||
|
-pri chybe vypíše hlášku na stderr
|
||||||
|
-podporuje aj zložitejšie výrazy so zátvorkami
|
||||||
|
-podporuje aj unárne mínus (napr. -3*(2+1))
|
||||||
|
|
||||||
|
## Stručný opis riešenia
|
||||||
|
Riešenie je rozdelené na 3 časti:
|
||||||
|
|
||||||
|
1. Tokenizácia
|
||||||
|
-rozdelenie vstupného reťazca na tokeny (čísla, operátory, funkcie, zátvorky)
|
||||||
|
|
||||||
|
2. Prevod infix -> postfix
|
||||||
|
-použitý algoritmus Shunting-yard
|
||||||
|
-rieši priority operátorov a zátvorky
|
||||||
|
|
||||||
|
3. Vyhodnotenie postfixu
|
||||||
|
-postfixový výraz sa vyhodnotí pomocou zásobníka (stack)
|
||||||
|
-pracuje sa s typom double
|
||||||
|
|
||||||
|
## Podmienky za ktorých program funguje
|
||||||
|
- výrazy musia byť syntakticky správne (napr. správne zátvorky)
|
||||||
|
- podporované operátory: + - * / ^
|
||||||
|
-podporované funkcie: sin(x), cos(x), sqrt(x), log(x), ln(x)
|
||||||
|
- podporované konštanty: pi, e
|
||||||
|
- sin a cos používajú radiány
|
||||||
|
- log(x) je log10(x)
|
||||||
|
- delenie nulou je ošetrené ako chyba
|
||||||
|
-doménové chyby:
|
||||||
|
- sqrt(x) vyžaduje x >= 0
|
||||||
|
- log(x) a ln(x) vyžadujú x > 0
|
||||||
|
|
||||||
|
## Použité zdroje
|
||||||
|
-Matej Hajduk (implementácia)
|
||||||
|
- ChatGPT (GPT-5.2), branch: sk2 (pomoc pri návrhu)
|
||||||
|
- Shunting-yard algoritmus (infix -> postfix)
|
||||||
|
-dokumentácia C:
|
||||||
|
- math.h (sin, cos, sqrt, log, log10, pow)
|
||||||
|
- strtod() (parsovanie čísiel)
|
||||||
|
-geek4geeks
|
||||||
|
|
||||||
475
sk2/calculator.c
Normal file
475
sk2/calculator.c
Normal file
@ -0,0 +1,475 @@
|
|||||||
|
#include "calculator.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - globalna chyba */
|
||||||
|
/* ---------------------------- */
|
||||||
|
static char g_err[128] = "OK";
|
||||||
|
|
||||||
|
/* - helper: set error */
|
||||||
|
static void set_err(const char *msg) {
|
||||||
|
strncpy(g_err, msg, sizeof(g_err)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - vrat error text */
|
||||||
|
const char *calc_error(void) {
|
||||||
|
return g_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - token typy */
|
||||||
|
/* ---------------------------- */
|
||||||
|
typedef enum {
|
||||||
|
T_NUM, /* - cislo */
|
||||||
|
T_OP, /* - operator */
|
||||||
|
T_FUNC, /* - funkcia */
|
||||||
|
T_LP, /* - ( */
|
||||||
|
T_RP /* - ) */
|
||||||
|
} TType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TType type;
|
||||||
|
double num; /* - hodnota */
|
||||||
|
char op; /* - + - * / ^ ~ */
|
||||||
|
char func[8]; /* - sin cos sqrt log ln */
|
||||||
|
} Token;
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - jednoduche pole tokenov */
|
||||||
|
/* ---------------------------- */
|
||||||
|
typedef struct {
|
||||||
|
Token *a;
|
||||||
|
int n;
|
||||||
|
int cap;
|
||||||
|
} TVec;
|
||||||
|
|
||||||
|
/* - init */
|
||||||
|
static void tvec_init(TVec *v) { v->a=NULL; v->n=0; v->cap=0; }
|
||||||
|
|
||||||
|
/* - free */
|
||||||
|
static void tvec_free(TVec *v) { free(v->a); tvec_init(v); }
|
||||||
|
|
||||||
|
/* - push */
|
||||||
|
static int tvec_push(TVec *v, Token t) {
|
||||||
|
if (v->n >= v->cap) {
|
||||||
|
int nc = v->cap ? v->cap*2 : 32;
|
||||||
|
Token *p = realloc(v->a, nc*sizeof(Token));
|
||||||
|
if (!p) return 0;
|
||||||
|
v->a = p;
|
||||||
|
v->cap = nc;
|
||||||
|
}
|
||||||
|
v->a[v->n++] = t;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - priorita operatorov */
|
||||||
|
/* ---------------------------- */
|
||||||
|
static int prec(char op) {
|
||||||
|
if (op=='~') return 4; /* - unarne minus */
|
||||||
|
if (op=='^') return 3; /* - mocnina */
|
||||||
|
if (op=='*' || op=='/') return 2; /* - nasob/del */
|
||||||
|
if (op=='+' || op=='-') return 1; /* - plus/minus */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - prava asociativita */
|
||||||
|
static int right_assoc(char op) {
|
||||||
|
return (op=='^' || op=='~'); /* - pow, unary */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - tokenize: string -> tokeny */
|
||||||
|
/* ---------------------------- */
|
||||||
|
static int tokenize(const char *s, TVec *out) {
|
||||||
|
/* - reset error */
|
||||||
|
set_err("OK");
|
||||||
|
|
||||||
|
tvec_init(out);
|
||||||
|
|
||||||
|
/* - prev token */
|
||||||
|
TType prev = T_OP; /* - na zaciatku */
|
||||||
|
|
||||||
|
while (*s) {
|
||||||
|
/* - skip spaces */
|
||||||
|
while (isspace((unsigned char)*s)) s++;
|
||||||
|
|
||||||
|
if (!*s) break;
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - cislo */
|
||||||
|
/* ---------------------------- */
|
||||||
|
if (isdigit((unsigned char)*s) || *s=='.') {
|
||||||
|
char *end = NULL;
|
||||||
|
double x = strtod(s, &end);
|
||||||
|
if (end==s) { set_err("Zle cislo"); return 0; }
|
||||||
|
|
||||||
|
Token t = {0};
|
||||||
|
t.type = T_NUM;
|
||||||
|
t.num = x;
|
||||||
|
|
||||||
|
if (!tvec_push(out, t)) { set_err("No memory"); return 0; }
|
||||||
|
|
||||||
|
s = end;
|
||||||
|
prev = T_NUM;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - ident: funkcia/konstanta */
|
||||||
|
/* ---------------------------- */
|
||||||
|
if (isalpha((unsigned char)*s)) {
|
||||||
|
char buf[16]={0};
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
while (isalpha((unsigned char)*s) && i<15) {
|
||||||
|
buf[i++] = (char)tolower((unsigned char)*s);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
buf[i]=0;
|
||||||
|
|
||||||
|
/* - konstanta pi */
|
||||||
|
if (!strcmp(buf,"pi")) {
|
||||||
|
Token t={0};
|
||||||
|
t.type=T_NUM;
|
||||||
|
t.num=M_PI;
|
||||||
|
if (!tvec_push(out,t)) { set_err("No memory"); return 0; }
|
||||||
|
prev=T_NUM;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - konstanta e */
|
||||||
|
if (!strcmp(buf,"e")) {
|
||||||
|
Token t={0};
|
||||||
|
t.type=T_NUM;
|
||||||
|
t.num=M_E;
|
||||||
|
if (!tvec_push(out,t)) { set_err("No memory"); return 0; }
|
||||||
|
prev=T_NUM;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - funkcie */
|
||||||
|
if (!strcmp(buf,"sin") || !strcmp(buf,"cos") ||
|
||||||
|
!strcmp(buf,"sqrt") || !strcmp(buf,"log") ||
|
||||||
|
!strcmp(buf,"ln")) {
|
||||||
|
|
||||||
|
Token t={0};
|
||||||
|
t.type=T_FUNC;
|
||||||
|
strncpy(t.func, buf, sizeof(t.func)-1);
|
||||||
|
|
||||||
|
if (!tvec_push(out,t)) { set_err("No memory"); return 0; }
|
||||||
|
prev=T_FUNC;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_err("Neznama funkcia");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - zatvorky */
|
||||||
|
/* ---------------------------- */
|
||||||
|
if (*s=='(') {
|
||||||
|
Token t={0};
|
||||||
|
t.type=T_LP;
|
||||||
|
if (!tvec_push(out,t)) { set_err("No memory"); return 0; }
|
||||||
|
s++;
|
||||||
|
prev=T_LP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*s==')') {
|
||||||
|
Token t={0};
|
||||||
|
t.type=T_RP;
|
||||||
|
if (!tvec_push(out,t)) { set_err("No memory"); return 0; }
|
||||||
|
s++;
|
||||||
|
prev=T_RP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - operatory */
|
||||||
|
/* ---------------------------- */
|
||||||
|
if (strchr("+-*/^", *s)) {
|
||||||
|
char op = *s;
|
||||||
|
|
||||||
|
/* - unary minus */
|
||||||
|
if (op=='-' && !(prev==T_NUM || prev==T_RP)) {
|
||||||
|
op='~';
|
||||||
|
}
|
||||||
|
|
||||||
|
Token t={0};
|
||||||
|
t.type=T_OP;
|
||||||
|
t.op=op;
|
||||||
|
|
||||||
|
if (!tvec_push(out,t)) { set_err("No memory"); return 0; }
|
||||||
|
|
||||||
|
s++;
|
||||||
|
prev=T_OP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_err("Neplatny znak");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out->n==0) { set_err("Prazdny vyraz"); return 0; }
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - infix -> postfix */
|
||||||
|
/* ---------------------------- */
|
||||||
|
static int to_postfix(const TVec *in, TVec *out) {
|
||||||
|
tvec_init(out);
|
||||||
|
|
||||||
|
TVec st; /* - operator stack */
|
||||||
|
tvec_init(&st);
|
||||||
|
|
||||||
|
for (int i=0;i<in->n;i++) {
|
||||||
|
Token t = in->a[i];
|
||||||
|
|
||||||
|
/* - cislo -> output */
|
||||||
|
if (t.type==T_NUM) {
|
||||||
|
if (!tvec_push(out,t)) { set_err("No memory"); goto fail; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - funkcia -> stack */
|
||||||
|
else if (t.type==T_FUNC) {
|
||||||
|
if (!tvec_push(&st,t)) { set_err("No memory"); goto fail; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - operator */
|
||||||
|
else if (t.type==T_OP) {
|
||||||
|
while (st.n>0) {
|
||||||
|
Token top = st.a[st.n-1];
|
||||||
|
|
||||||
|
/* - funkcia ma prioritu */
|
||||||
|
if (top.type==T_FUNC) {
|
||||||
|
if (!tvec_push(out,top)) { set_err("No memory"); goto fail; }
|
||||||
|
st.n--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - operator priorita */
|
||||||
|
if (top.type==T_OP) {
|
||||||
|
int p1 = prec(t.op);
|
||||||
|
int p2 = prec(top.op);
|
||||||
|
|
||||||
|
/* - pop pri vacsej priorite */
|
||||||
|
if (p2>p1 || (p2==p1 && !right_assoc(t.op))) {
|
||||||
|
if (!tvec_push(out,top)) { set_err("No memory"); goto fail; }
|
||||||
|
st.n--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!tvec_push(&st,t)) { set_err("No memory"); goto fail; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - ( -> stack */
|
||||||
|
else if (t.type==T_LP) {
|
||||||
|
if (!tvec_push(&st,t)) { set_err("No memory"); goto fail; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - ) -> pop do ( */
|
||||||
|
else if (t.type==T_RP) {
|
||||||
|
int ok=0;
|
||||||
|
|
||||||
|
while (st.n>0) {
|
||||||
|
Token top = st.a[--st.n];
|
||||||
|
|
||||||
|
if (top.type==T_LP) { ok=1; break; }
|
||||||
|
|
||||||
|
if (!tvec_push(out,top)) { set_err("No memory"); goto fail; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) { set_err("Zle zatvorky"); goto fail; }
|
||||||
|
|
||||||
|
/* - po zatvorke funkcia */
|
||||||
|
if (st.n>0 && st.a[st.n-1].type==T_FUNC) {
|
||||||
|
Token f = st.a[--st.n];
|
||||||
|
if (!tvec_push(out,f)) { set_err("No memory"); goto fail; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - pop zvysok */
|
||||||
|
while (st.n>0) {
|
||||||
|
Token top = st.a[--st.n];
|
||||||
|
if (top.type==T_LP) { set_err("Zle zatvorky"); goto fail; }
|
||||||
|
if (!tvec_push(out,top)) { set_err("No memory"); goto fail; }
|
||||||
|
}
|
||||||
|
|
||||||
|
tvec_free(&st);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
tvec_free(&st);
|
||||||
|
tvec_free(out);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - stack double */
|
||||||
|
/* ---------------------------- */
|
||||||
|
typedef struct {
|
||||||
|
double *a;
|
||||||
|
int n;
|
||||||
|
int cap;
|
||||||
|
} DStack;
|
||||||
|
|
||||||
|
static void ds_init(DStack *s){ s->a=NULL; s->n=0; s->cap=0; }
|
||||||
|
static void ds_free(DStack *s){ free(s->a); ds_init(s); }
|
||||||
|
|
||||||
|
static int ds_push(DStack *s, double x){
|
||||||
|
if (s->n>=s->cap){
|
||||||
|
int nc=s->cap? s->cap*2:32;
|
||||||
|
double *p=realloc(s->a,nc*sizeof(double));
|
||||||
|
if(!p) return 0;
|
||||||
|
s->a=p; s->cap=nc;
|
||||||
|
}
|
||||||
|
s->a[s->n++]=x;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds_pop(DStack *s, double *x){
|
||||||
|
if(s->n==0) return 0;
|
||||||
|
*x=s->a[--s->n];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - apply function */
|
||||||
|
/* ---------------------------- */
|
||||||
|
static int apply_func(const char *f, double x, double *out){
|
||||||
|
if(!strcmp(f,"sin")) { *out=sin(x); return 1; }
|
||||||
|
if(!strcmp(f,"cos")) { *out=cos(x); return 1; }
|
||||||
|
|
||||||
|
if(!strcmp(f,"sqrt")){
|
||||||
|
if(x<0) { set_err("sqrt domena"); return 0; }
|
||||||
|
*out=sqrt(x);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcmp(f,"log")){
|
||||||
|
if(x<=0) { set_err("log domena"); return 0; }
|
||||||
|
*out=log10(x);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcmp(f,"ln")){
|
||||||
|
if(x<=0) { set_err("ln domena"); return 0; }
|
||||||
|
*out=log(x);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_err("Zla funkcia");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - eval postfix */
|
||||||
|
/* ---------------------------- */
|
||||||
|
static int eval_postfix(const TVec *post, double *out){
|
||||||
|
DStack st;
|
||||||
|
ds_init(&st);
|
||||||
|
|
||||||
|
for(int i=0;i<post->n;i++){
|
||||||
|
Token t=post->a[i];
|
||||||
|
|
||||||
|
/* - cislo -> push */
|
||||||
|
if(t.type==T_NUM){
|
||||||
|
if(!ds_push(&st,t.num)){ set_err("No memory"); goto fail; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - funkcia */
|
||||||
|
else if(t.type==T_FUNC){
|
||||||
|
double a,r;
|
||||||
|
if(!ds_pop(&st,&a)){ set_err("Syntax"); goto fail; }
|
||||||
|
if(!apply_func(t.func,a,&r)) goto fail;
|
||||||
|
if(!ds_push(&st,r)){ set_err("No memory"); goto fail; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - operator */
|
||||||
|
else if(t.type==T_OP){
|
||||||
|
|
||||||
|
/* - unary minus */
|
||||||
|
if(t.op=='~'){
|
||||||
|
double a;
|
||||||
|
if(!ds_pop(&st,&a)){ set_err("Syntax"); goto fail; }
|
||||||
|
if(!ds_push(&st,-a)){ set_err("No memory"); goto fail; }
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - binarne */
|
||||||
|
double b,a,r;
|
||||||
|
if(!ds_pop(&st,&b) || !ds_pop(&st,&a)){ set_err("Syntax"); goto fail; }
|
||||||
|
|
||||||
|
if(t.op=='+') r=a+b;
|
||||||
|
else if(t.op=='-') r=a-b;
|
||||||
|
else if(t.op=='*') r=a*b;
|
||||||
|
else if(t.op=='/'){
|
||||||
|
if(b==0){ set_err("Delenie nulou"); goto fail; }
|
||||||
|
r=a/b;
|
||||||
|
}
|
||||||
|
else if(t.op=='^'){
|
||||||
|
r=pow(a,b);
|
||||||
|
if(isnan(r) || isinf(r)){ set_err("Pow domena"); goto fail; }
|
||||||
|
}
|
||||||
|
else { set_err("Zly operator"); goto fail; }
|
||||||
|
|
||||||
|
if(!ds_push(&st,r)){ set_err("No memory"); goto fail; }
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
set_err("Syntax");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - musi ostat 1 */
|
||||||
|
if(st.n!=1){ set_err("Syntax"); goto fail; }
|
||||||
|
|
||||||
|
*out=st.a[0];
|
||||||
|
ds_free(&st);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ds_free(&st);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
/* - hlavna funkcia */
|
||||||
|
/* ---------------------------- */
|
||||||
|
calc_status_t calc_evaluate(const char *expr, double *out){
|
||||||
|
if(!expr || !out){ set_err("NULL"); return CALC_ERR; }
|
||||||
|
|
||||||
|
TVec toks, post;
|
||||||
|
tvec_init(&toks);
|
||||||
|
tvec_init(&post);
|
||||||
|
|
||||||
|
/* - tokenize */
|
||||||
|
if(!tokenize(expr,&toks)){ tvec_free(&toks); return CALC_ERR; }
|
||||||
|
|
||||||
|
/* - postfix */
|
||||||
|
if(!to_postfix(&toks,&post)){ tvec_free(&toks); return CALC_ERR; }
|
||||||
|
|
||||||
|
/* - eval */
|
||||||
|
if(!eval_postfix(&post,out)){
|
||||||
|
tvec_free(&toks);
|
||||||
|
tvec_free(&post);
|
||||||
|
return CALC_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
tvec_free(&toks);
|
||||||
|
tvec_free(&post);
|
||||||
|
return CALC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
18
sk2/calculator.h
Normal file
18
sk2/calculator.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef CALCULATOR_H
|
||||||
|
#define CALCULATOR_H
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CALC_OK = 0,
|
||||||
|
CALC_ERR
|
||||||
|
} calc_status_t;
|
||||||
|
|
||||||
|
/* - vyhodnoti vyraz */
|
||||||
|
/* - expr: vstup */
|
||||||
|
/* - out: vysledok */
|
||||||
|
calc_status_t calc_evaluate(const char *expr, double *out);
|
||||||
|
|
||||||
|
/* - text chyby */
|
||||||
|
const char *calc_error(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
35
sk2/main.c
Normal file
35
sk2/main.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "calculator.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* - pekny vypis */
|
||||||
|
static void print_double(double x){
|
||||||
|
/* - cele cislo */
|
||||||
|
if (fabs(x - round(x)) < 1e-9) {
|
||||||
|
printf("%.0f\n", round(x));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* - min 2 des */
|
||||||
|
printf("%.2f\n", x);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void){
|
||||||
|
char line[512];
|
||||||
|
|
||||||
|
/* - citaj riadky */
|
||||||
|
while (fgets(line,sizeof(line),stdin)){
|
||||||
|
double res;
|
||||||
|
|
||||||
|
/* - vypocitaj */
|
||||||
|
if (calc_evaluate(line,&res) != CALC_OK){
|
||||||
|
fprintf(stderr,"Chyba: %s\n", calc_error());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* - vypis */
|
||||||
|
print_double(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user