/* program kalkulacka - pocitanie v reverznej polskej notacii s neobmedzene velkymi cislami prikazy: + - * / ^(=mocnina) p (=vypis vysledku) */ #include #include #include struct Cislo{ size_t dlzka; char znam;//znamienko int* num; struct Cislo* next; }; //deklaracie dolezitych funkciio** zasobnik); void del(struct Cislo** zasobnik); void mocnina(struct Cislo** zasobnik); void dosla_pamat(void) { fprintf(stderr,"nedostatok pamate!"); abort(); } int char2int(int znak) { /*pride mi pomerne zbytocne pouzivat atoi s jej obmedzeniami ako nutnost zistovat ci cislo nebolo 0 a prerabanim char-u na string */ switch (znak) { case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '0': return 0; break; case '1': return 1; break; case '2': return 2; case '3': return 3; break; case '4': return 4; break; case '5': return 5; break; case '6': return 6; break; case '7': return 7; break; case '8': return 8; case '9': return 9; break; default: return -1; } } int zisti_vacsie(const struct Cislo *c1,const struct Cislo* c2) /*pracuje s absolutnymi hodnotami cisel. vracia 1 ak je 1.cislo vacsie v abs.hodnote alebo 2.ak je vacsie 2.cislo, 0 ak su zhodne*/ /*predpoklada sa ze obe cisla su kladne*/ { size_t dlzka1,dlzka2; size_t i1=0,i2=0; dlzka1=c1->dlzka; dlzka2=c2->dlzka; while (c1->num[i1]==0) i1++; while (c2->num[i2]==0) i2++; if (dlzka1-i1>dlzka2-i2) return 1; else if (dlzka1-i10) { if (c1->num[i1]>c2->num[i2]) return 1; else if (c1->num[i1]num[i2]) return 2; else { i1++; i2++; } } return 0;//ak dojde f-cia az sem tak su obe cisla rovnake } } void odcitaj(struct Cislo** zasobnik,int nemaz) //parameter nemaz je skoro vzdy 0.ak nie je,to sa vyuzije pri deleni, //vtedy sa vysledok vlozi do zasobnika namiesto cis1 a cis2 ostane na svojom mieste kvoli usetreniu pamate { struct Cislo *cis1,*cis2,*vysledok; if (!(*zasobnik)) printf("prazdny zasobnik!"); else if (!(*zasobnik)->next) printf("iba jedno cislo na zasobniku!"); else { cis2=(*zasobnik); cis1=(*zasobnik)->next; if (cis2->znam=='+' && cis1->znam=='-') { cis2->znam='+'; scitaj(zasobnik);//scita a nastavi znamienko - } else if(cis2->znam=='-'&&cis1->znam=='+') { cis2->znam='+'; scitaj(zasobnik); } else if(cis1->znam=='-'&&cis2->znam=='-')//prehodit a odcitat { cis1->znam='+'; cis2->znam='+'; cis2->next=cis1->next; cis1->next=cis2; (*zasobnik)=cis1; odcitaj(zasobnik,0); } else { int vacsie=zisti_vacsie(cis1,cis2); if (!vacsie) { free(cis2->num); free(cis2); cis1->dlzka=1; free(cis1->num); cis1->num=malloc(sizeof(int)); if (!cis1->num) dosla_pamat(); cis1->num[0]=0; (*zasobnik)=cis1; } else if (vacsie==2)//ak je druhe cislo vacsie,odcita sa 1. od 2. a znam je - { cis2->next=cis1->next; cis1->next=cis2; (*zasobnik)=cis1; cis2->znam='+'; odcitaj(zasobnik,0); (*zasobnik)->znam='-'; } else { size_t dlzka_vysl; size_t dlzka1=cis1->dlzka; size_t dlzka2=cis2->dlzka; int prenos=0; vysledok=malloc(sizeof(struct Cislo)); if (!vysledok) dosla_pamat(); vysledok->next=(*zasobnik)->next->next; vysledok->znam='+'; if (dlzka1>dlzka2) dlzka_vysl=dlzka1; else dlzka_vysl=dlzka2; vysledok->num=malloc(sizeof(int)*dlzka_vysl); if (!vysledok) dosla_pamat(); vysledok->dlzka=dlzka_vysl; while(dlzka_vysl>0) { if (dlzka1>0 &&dlzka2>0) { if ((cis1->num[dlzka1-1]-(cis2->num[dlzka2-1]+prenos))>-1) { vysledok->num[dlzka_vysl-1]=(cis1->num[dlzka1-1]-(cis2->num[dlzka2-1]+prenos)); prenos=0; } else { vysledok->num[dlzka_vysl-1]=(10+cis1->num[dlzka1-1]-(cis2->num[dlzka2-1]+prenos)); prenos=1; } dlzka_vysl--; dlzka1--; dlzka2--; } else if (dlzka1>0 &&dlzka2==0) { if ((cis1->num[dlzka1-1]-prenos)>-1) { vysledok->num[dlzka_vysl-1]=(cis1->num[dlzka1-1]-prenos); prenos=0; } else { vysledok->num[dlzka_vysl-1]=(10+cis1->num[dlzka1-1]-prenos); prenos=1; } dlzka_vysl--; dlzka1--; } else if (dlzka1==0 &&dlzka2>0) { if ((cis2->num[dlzka2-1]-prenos)>-1) { vysledok->num[dlzka_vysl-1]=(cis2->num[dlzka2-1]-prenos); prenos=0; } else { vysledok->num[dlzka_vysl-1]=(10+cis2->num[dlzka2-1]-prenos); prenos=1; } dlzka_vysl--; dlzka2--; } } free(cis1->num); free(cis1); if (nemaz) { cis2->next=vysledok; (*zasobnik)=cis2; } else { (*zasobnik)=vysledok; free(cis2->num); free(cis2); } } } } } void scitaj(struct Cislo** zasobnik) { struct Cislo* cis1,*cis2,*vysledok; if (!(*zasobnik)) printf("prazdny zasobnik!"); else if (!(*zasobnik)->next) printf("iba jedno cislo na zasobniku!"); else { cis1=(*zasobnik); cis2=(*zasobnik)->next; if (cis2->znam=='-' && cis1->znam=='+')//prehod cisla a odcitaj ich { cis2->znam='+'; cis1->next=cis2->next; cis2->next=cis1; (*zasobnik)=cis2; odcitaj(zasobnik,0); } else if (cis1->znam=='-' &&cis2->znam=='+') { cis1->znam='-'; odcitaj(zasobnik,0); } else { size_t dlzka_vysl; size_t dlzka1=cis1->dlzka; size_t dlzka2=cis2->dlzka; int prenos=0; vysledok=malloc(sizeof(struct Cislo)); if (!vysledok) dosla_pamat(); vysledok->next=(*zasobnik)->next->next; vysledok->znam='+'; if (dlzka1>dlzka2) dlzka_vysl=dlzka1; else dlzka_vysl=dlzka2; if (cis1->num[0]!=0 && cis2->num[0]!=0) dlzka_vysl++; //aby bolo dost miesta na cislo o jednu //cifru dlhsie vysledok->num=malloc(sizeof(int)*dlzka_vysl); if (!vysledok) dosla_pamat(); vysledok->dlzka=dlzka_vysl; while(dlzka_vysl>0) { if (dlzka1>0 &&dlzka2>0) { vysledok->num[dlzka_vysl-1]=(cis1->num[dlzka1-1]+cis2->num[dlzka2-1]+prenos)%10; if ((cis1->num[dlzka1-1]+cis2->num[dlzka2-1]+prenos)>9) prenos=1; else prenos=0; dlzka_vysl--; dlzka1--; dlzka2--; } else if (dlzka1>0 &&dlzka2==0) { vysledok->num[dlzka_vysl-1]=(cis1->num[dlzka1-1]+prenos)%10; if ((cis1->num[dlzka1-1]+prenos)>9) prenos=1; else prenos=0; dlzka_vysl--; dlzka1--; } else if (dlzka1==0 &&dlzka2>0) { vysledok->num[dlzka_vysl-1]=(cis2->num[dlzka2-1]+prenos)%10; if ((cis2->num[dlzka2-1]+prenos)>9) prenos=1; else prenos=0; dlzka_vysl--; dlzka2--; } else if (dlzka1==0 &&dlzka2==0) { vysledok->num[dlzka_vysl-1]=prenos; dlzka_vysl--; } } if (cis1->znam=='-'&&cis2->znam=='-') vysledok->znam='-'; (*zasobnik)=vysledok; free(cis1->num); free(cis1); free(cis2->num); free(cis2); } } } void nasob(struct Cislo** zasobnik) { struct Cislo* cis1,*cis2,*vysledok; if (!(*zasobnik)) printf("prazdny zasobnik!"); else if (!(*zasobnik)->next) printf("iba jedno cislo na zasobniku!"); else { cis1=(*zasobnik)->next; cis2=(*zasobnik); vysledok=malloc(sizeof(struct Cislo)); if (!vysledok) dosla_pamat(); vysledok->next=(*zasobnik)->next->next; if (cis1->znam!=cis2->znam) vysledok->znam='-'; else vysledok->znam='+'; if ((cis1->dlzka==1&&cis1->num[0]==0)||(cis2->dlzka==1&&cis2->num[0]==0)) { vysledok->dlzka=1; vysledok->num=malloc(sizeof(int)); if (!vysledok->num) dosla_pamat(); vysledok->num[0]=1; free(cis1->num); free(cis1); free(cis2->num); free(cis2); (*zasobnik)=vysledok; } if (cis1->dlzka==1&&cis1->num[0]==1) { free(vysledok->num); free(vysledok); vysledok=cis2; free(cis1->num); free(cis1); (*zasobnik)=vysledok; } if (cis2->dlzka==1&&cis2->num[0]==1) { free(vysledok->num); free(vysledok); vysledok=cis1; free(cis2->num); free(cis2); (*zasobnik)=vysledok; } else { size_t posun=0; char znam=vysledok->znam; struct Cislo* tmp; size_t i1,i2; int prenos=0; size_t dlzka=cis1->dlzka; dlzka=dlzka+cis2->dlzka-1; vysledok->znam='+'; vysledok->num=malloc(sizeof(int)*dlzka); for (i1=0;i1num[i1]=0; if (!vysledok->num) dosla_pamat(); vysledok->dlzka=dlzka; for (i2=cis2->dlzka-1;i2+1>0;i2--) { size_t j; tmp=malloc(sizeof(struct Cislo)); if (!tmp) dosla_pamat(); tmp->next=vysledok; tmp->dlzka=cis1->dlzka+1+posun; tmp->znam='+'; tmp->num=malloc((tmp->dlzka) * sizeof(int)); if (!tmp->num) dosla_pamat(); for (j=0;jdlzka;j++) tmp->num[j]=0; for (i1=cis1->dlzka-1;i1+1>0;i1--) { tmp->num[i1-posun]=(cis2->num[i2]*cis1->num[i1]+prenos)%10; prenos=(cis2->num[i2]*cis1->num[i1]+prenos)/10; } tmp->num[0]=prenos; prenos=0; scitaj(&tmp); vysledok=tmp; } vysledok->next=(*zasobnik)->next->next; (*zasobnik)=vysledok; vysledok->znam=znam; free(cis1->num); free(cis1); free(cis2->num); free(cis2); } } } void del(struct Cislo** zasobnik) { struct Cislo* cis1,*cis2,*vysledok,*tmp; if (!(*zasobnik)) printf("prazdny zasobnik!"); else if (!(*zasobnik)->next) printf("iba jedno cislo na zasobniku!"); else { int vacsie; cis2=(*zasobnik); cis1=(*zasobnik)->next; //osetrit delenie 0 if (cis2->dlzka==1 && cis2->num[0]==0) { fprintf(stderr,"delenie nulou!"); abort(); } vacsie=zisti_vacsie(cis1,cis2); vysledok=malloc(sizeof(struct Cislo)); if (!vysledok) dosla_pamat(); vysledok->next=(*zasobnik)->next->next; if (cis1->znam!=cis2->znam) vysledok->znam='-'; else vysledok->znam='+'; if (vacsie==0 || vacsie==2) { vysledok->dlzka=1; vysledok->num=malloc(sizeof(int)); if (!vysledok->num) dosla_pamat(); if (vacsie==0) vysledok->num[0]=1; else vysledok->num[0]=0; free(cis1->num); free(cis1); free(cis2->num); free(cis2); (*zasobnik)=vysledok; } else {//cis1 je vacsie v abs hodnote cis1->znam='+'; cis2->znam='+'; vysledok->num=malloc(sizeof(int)); vysledok->dlzka=1; vysledok->num[0]=0; vysledok->next=0; while (zisti_vacsie(cis1,cis2)==1) { tmp=malloc(sizeof(struct Cislo)); if (!tmp) dosla_pamat(); tmp->num=malloc(sizeof(int)); if(!tmp->num) dosla_pamat(); tmp->dlzka=1; tmp->num[0]=1; tmp->next=vysledok; vysledok=tmp; scitaj(&vysledok); odcitaj(zasobnik,1); cis1=(*zasobnik)->next; } vysledok->next=(*zasobnik)->next->next; (*zasobnik)=vysledok; if (zisti_vacsie(cis1,cis2)==0) { tmp=malloc(sizeof(struct Cislo)); if (!tmp) dosla_pamat(); tmp->num=malloc(sizeof(int)); if(!tmp->num) dosla_pamat(); tmp->dlzka=1; tmp->num[0]=1; tmp->next=vysledok; (*zasobnik)=tmp; scitaj(zasobnik); } free(cis1->num); free(cis1); free(cis2->num); free(cis2); } } } void mocnina(struct Cislo** zasobnik) { } void vypis(struct Cislo** zasobnik) { size_t i; struct Cislo* tmp; if (!*zasobnik) printf("prazdny zasobnik!"); else { if ((*zasobnik)->znam=='-') printf("-"); for (i=0;i<(*zasobnik)->dlzka;++i) printf("%i",(*zasobnik)->num[i]); tmp=*zasobnik; (*zasobnik)=(*zasobnik)->next; free(tmp->num); free(tmp); } printf("\n"); } int main(void) { int cislo; struct Cislo* aktualne=0; struct Cislo* zasobnik=0; int znak; char znamienko=0; printf("postfixova kalkulacka\n"); printf("Zadaj vyraz: "); znak=getchar(); while (znak!=EOF) { if (znak=='\n') { znak=getchar(); continue; } switch (znak) { case '+': znamienko='+'; break; case '-': znamienko='-'; break; case 'p': vypis(&zasobnik); break; case '^': mocnina(&zasobnik); break; case '/': del(&zasobnik); break; case '*': nasob(&zasobnik); break; default: cislo=char2int(znak); if (cislo!=-1){ aktualne=malloc(sizeof(struct Cislo)); if (!aktualne) dosla_pamat(); aktualne->dlzka=1; aktualne->znam='+'; aktualne->num=malloc(sizeof(int)*aktualne->dlzka); if (!aktualne->num) dosla_pamat(); aktualne->num[aktualne->dlzka-1]=cislo; aktualne->next=zasobnik; zasobnik=aktualne; znamienko=0; } else printf("chybne zadany vstup!\n"); } znak=getchar(); if (znak==EOF) break; if (znak=='\n') { if (!aktualne && znamienko=='+') scitaj(&zasobnik); else if (!aktualne && znamienko=='-') odcitaj(&zasobnik,0); znamienko=0; if (aktualne) aktualne=0; } else while (znak!=EOF && znak!='\n') { cislo=char2int(znak); if (cislo!=-1) { if (!aktualne) { aktualne=malloc(sizeof(struct Cislo)); if (!aktualne) dosla_pamat(); aktualne->dlzka=0; aktualne->znam=znamienko; aktualne->num=0; aktualne->next=zasobnik; zasobnik=aktualne; znamienko=0; } aktualne->dlzka++; aktualne->num=realloc(aktualne->num,(sizeof(int)*aktualne->dlzka)); if (!aktualne->num) dosla_pamat(); aktualne->num[aktualne->dlzka-1]=cislo; } else //cislo==-1 ->zly znak na vstupe { printf("chybne zadany vstup!"); if (aktualne){ zasobnik=aktualne->next; //zmazanie aktual.cisla zo zasobnika free(aktualne->num); free(aktualne); aktualne=0; } } znak=getchar(); } znamienko=0; aktualne=0; znak=getchar(); } return 0; }