You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

382 lines
8.9 KiB
C

/* ------------------------------------------------------------------------- */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ------------------------------------------------------------------------- */
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<strlen(expr));
veremp--; //Ez mindig az utolso ervenyes verem-char-ra indexel ra!
*result=getnumber(verem,szamok,0,veremp);
free(szamok);
free(verem);
free(expr);
return(NULL);
};
/* ------------------------------------------------------------------------- */