/* ------------------------------------------------------------------------- */ #include #include #include #include /* ------------------------------------------------------------------------- */ double getbinary(char *str,int *ptr) { double bin=0; while (*str=='0' || *str=='1') { bin = (bin*2) + (*str++ -'0'); *ptr += 1; } return (bin); }; /* ------------------------------------------------------------------------- */ double getdecimal(char *str,int *ptr) { double dec=0; int i=0,end=0,neg=0,fraction=0; if (str[i]=='-') {neg=1;i++;}; do { if ((str[i] >='0') && (str[i] <='9')) dec = (dec * 10) + (str[i] - '0'); else if (str[i] == '.') fraction=i; else end=1; i++; } while(!end); if (neg) dec *= -1; if (fraction) dec = dec/pow(10,(i-2-fraction)); *ptr=*ptr+i-1; return (dec); }; /**************/ double gethexa(char *str,int *ptr){ double hex=0; int end=0; while (*str && !end) { if ((*str >='0') && (*str <='9')) hex = (hex * 16) + (*str - '0'); else if ((*str >='a') && (*str <= 'f')) hex = (hex * 16) + (*str - 'a' + 10); else if ((*str >='A') && (*str <= 'F')) hex = (hex * 16) + (*str - 'A' + 10); else end = 1; if (!end) { str++; *ptr += 1; } } return (hex); }; /*******************************************************************/ void veremcompress(char * verem,double * szamok,int begin,int * end){ /* * Az adott tartomanyban a verembol kiszedi a felesleges zarojeleket, * es az ures (' ') bejegyzeseket * */ int i,j,lyuk; int zarojel,job; // kiszedem a lyukakat, aztan a zarjeleket, aztan megint lyuk, es igy tovabb... do { job=0; // lyukszedes: do { lyuk=0; for (i=begin;i<=*end;i++) { if (verem[i]==' ') { lyuk=1; for (j=i;j<*end;j++) {verem[j]=verem[j+1]; szamok[j]=szamok[j+1];}; verem[j]=' '; (*end)--; }; }; } while (lyuk); // a felesleges zarojeleket szedem ki: zarojel=0; for (i=begin;i<=*end;i++) {if (verem[i]=='(') {if (verem[i+1]==')') {verem[i]=' '; verem[i+1]=' '; job=1;} else if (verem[i+1]=='1' && verem[i+2]==')') {verem[i]=' '; verem[i+2]=' '; job=1;} else zarojel++; }; if (verem[i]==')') zarojel--; }; if (zarojel!=0) {printf("Zarojelezesi hiba!\n");exit(-1);}; } while (job); //ellenorzom, hogy van-e ket szam egymas mogott, hogy nincs koztuk muveleti jel. //ilyen nem lehet alapbol, tehat input string hiba for (i=begin;i<*end;i++) if (verem[i]=='1' && verem[i+1]=='1') {printf("Bemeneti stringben hiba!\n");exit(-1);}; }; /*******************************************************************/ double getnumber(char *verem,double *szamok,int begin,int end){ int i,j,zarojel,job; //Eloszoris az indulaskor is lehetseges felesleges szokozoket, es a felesleges zarojeleket szurom ki: //Ha a zarojelezesben hiba van, az is kiderul itt! veremcompress(verem,szamok,begin,&end); //Azutan eloszor a zarojelben levo dolgokat szamolom ki, hogy vegul egy () se maradjon. do { job=0; for (i=begin;i<=end;i++) {if ((verem[i]=='(') || (verem[i]==')')) job=1;}; if (job) {for (i=begin;verem[i]!='(';i++); j=i;zarojel=1; do {j++; if (verem[j]=='(') zarojel++; if (verem[j]==')') zarojel--; } while(zarojel!=0); getnumber(verem,szamok,i+1,j-1); verem[i]=' '; verem[j]=' '; veremcompress(verem,szamok,begin,&end); }; } while(job!=0); // Mostmar garantaltan nincs zarojel, johet sorrendben a tovabbi szamolas: while(begin!=end) { // Elso korben HATVANYozast keresek. for (i=begin;i<=end;i++) {if (verem[i]=='^') { szamok[i]=pow(szamok[i-1],szamok[i+1]); verem[i]='1'; verem[i-1]=' '; verem[i+1]=' '; veremcompress(verem,szamok,begin,&end); }; }; // Masodik korben a SZORZASokkal es az OSZTASokkal vegzek for (i=begin;i<=end;i++) {if (verem[i]=='*') {szamok[i]=szamok[i-1]*szamok[i+1]; verem[i]='1'; verem[i-1]=' '; verem[i+1]=' '; veremcompress(verem,szamok,begin,&end); }; if (verem[i]=='/') {szamok[i]=szamok[i-1]/szamok[i+1]; verem[i]='1'; verem[i-1]=' '; verem[i+1]=' '; veremcompress(verem,szamok,begin,&end); }; }; // Harmadik korben az OSSZEADAS es a KIVONAS van mar csak for (i=begin;i<=end;i++) {if (verem[i]=='+') {szamok[i]=szamok[i-1]+szamok[i+1]; verem[i]='1'; verem[i-1]=' '; verem[i+1]=' '; veremcompress(verem,szamok,begin,&end); }; if (verem[i]=='-') {szamok[i]=szamok[i-1]-szamok[i+1]; verem[i]='1'; verem[i-1]=' '; verem[i+1]=' '; veremcompress(verem,szamok,begin,&end); }; }; }; return(szamok[begin]); }; /*******************************************************************/ const char* calc(char *kifejezes,double * result){ double *szamok; char *verem; int i,veremp,job,j; char *expr; char *err; char *ptr; // First I remove the spaces from the expression if (NULL==(expr=(char*)calloc(strlen(kifejezes),1))) { printf("Out of memory!\n"); exit(-1); }; ptr = expr; while (*kifejezes) // strip spaces { if (*kifejezes != ' ') *ptr++ = *kifejezes; kifejezes++; } *ptr++ = 0; if ( NULL == (verem=(char*)malloc( strlen(expr)+1 )) ) { printf("Out of memory!\n"); exit(-1); }; if ( NULL == (szamok=(double*)malloc( (strlen(expr)+1) * sizeof(double) )) ) { printf("Out of memory!\n"); exit(-1); }; /* * Beolvasom a expr-bol a szamokat, es a muveleti jeleket. * * Veremtartalom a kifejezesben levo elemeket tartalmazza: * * (,),+,-,*,/,^ A szokasos muveleti jelek (es csak ezek!) * 1 : ezen a helyen egy szam all, a szamok altal tartalmazott tombbol keresheto ki, melyik. * */ //A legelso karakter nem lehet barmi, kulon vizsgalom: i=veremp=0; switch(expr[i]) { case '(' : verem[veremp++]='(';i++;break; case ')' : return ("zarojelezesi hiba"); break; case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; case '+' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[++i],&i); break; case '-' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; case '%' : verem[veremp]='1'; i++; szamok[veremp++]=getbinary(&expr[i],&i); break; case '$' : verem[veremp]='1'; i++; szamok[veremp++]=gethexa(&expr[i],&i); break; default : return ("hiba0"); }; if (strlen(expr)!=i) //most a tovabbi karakterek johetnek: do { if ((verem[veremp-1]=='1') || (verem[veremp-1]==')')) { switch(expr[i]) { case ')': case '+': case '-': case '*': case '/': case '^': verem[veremp++]=expr[i++]; break; default: return ("hiba1"); }; }; if (verem[veremp-1]=='(') { switch(expr[i]) { case '(' : verem[veremp++]='(';i++;break; case ')' : verem[veremp++]=')';i++;break; case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; case '+' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[++i],&i); break; case '-' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; case '%' : verem[veremp]='1'; i++; szamok[veremp++]=getbinary(&expr[i],&i); break; case '$' : verem[veremp]='1'; i++; szamok[veremp++]=gethexa(&expr[i],&i); break; default : return ("hiba2"); }; }; if ((verem[veremp-1]=='^') || (verem[veremp-1]=='*') || (verem[veremp-1]=='/') || (verem[veremp-1]=='+') || (verem[veremp-1]=='-')) { switch(expr[i]) { case '(' : verem[veremp++]='(';i++;break; case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; case '+' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[++i],&i); break; case '-' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; case '%' : verem[veremp]='1'; i++; szamok[veremp++]=getbinary(&expr[i],&i); break; case '$' : verem[veremp]='1'; i++; szamok[veremp++]=gethexa(&expr[i],&i); break; default : return ("hiba3"); }; }; } while (i