?
Solved

Implemeting an Open Addressing Hash Tables  and reading data from a file Parsers using C

Posted on 2003-03-20
13
Medium Priority
?
1,032 Views
Last Modified: 2013-11-18
I am working on something right now and I Need an idea on how to start it.
Here is the scenrio

This programming projectis to write a simple expression parser The parser program repeatedly asks the user for an arithmetic expression and outputs its value. To make things a bit more interesting, the expressions may contain variables and functions.


As it runs, the program prompts the user for an assignment. The user might input


foo = 450*(bar/baz)


where bar and baz are variables defined in previous assignments. The program will first evaluate the expression in the right side of the assignment, and assign the result to the variable on the left side. The variable foo has now been defined and may appear in future expressions.


The expressions may consist of numbers (which may be integers or decimal numbers), previously defined variables and functions. A function consists of a function name immediately followed by the list of parameters in parentheses. The parser must recognize and evaluate the functions sin, cos, abs and max, where the first three functions take a single parameter, and the max function takes arbitrary many parameters, separated by commas.


For example, some assignments given to the parser might be


x = 1*2*3*4*5-5*-4*-3*-2*-1

y = 1.11 + 2.22 + -3.33 * 4.4444444

z = max(x,y,x*y,x+y,x/y)

quitealongvariablename = sin(cos(sin(cos(2))))


For these assignments, the program should output 0, -11.47, 0 and 0.7952, respectively. (The accuracy of your program may differ from these depending on how many decimals you choose to output.)


For simplicity, the program may assume that all expressions given to it are syntactically correct, so there is no need to implement error handling or error recovery in your parser. Also the expressions are guaranteed to contain only previously defined variables. Other rules for this project are:


The parser may do all the computations using the double type. There is no need to specifically handle overflows and numerical inaccuracy errors.


The input can be trusted to be a syntactically correct expression. However, it might contain spaces wherever they are allowed.


Multiplication is always used explicitly. For example, the expression x(y+z) would be syntactically incorrect, and is given in full as x*(y+z).


The parser should give multiplication and division operations a higher precedence than addition and subtraction. The associativity of the same-precedence operations may be arbitrary, though. (Especially both addition and subtraction may be right-associative, which would, for example, make 1-2+3 equal –4 instead of 2.)


Variable names shall only contain the lowercase characters a,…,z and cannot be more than 100 characters long. The function names cannot be used as variable names, although a variable name can begin with a function name.


Your parser program will have to store the variables that are declared by the user, along with their corresponding values and you must do this by implementing an open addressing hash table. I can only include the follwing libraries for
input and output, string handling and the calculation of mathematical functions sin and cos.




0
Comment
Question by:Shooter19
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
13 Comments
 
LVL 8

Accepted Solution

by:
adg080898 earned 195 total points
ID: 8180397
You need a lexical analyser (lexx or one of its clones) to extract numbers, symbols, names, etc.

Then you need a parser (yacc or one of its clones) to handle precedence and nesting.

The rules in the parser will create a tree structure of the expressions. Each node may be an operation or a constant. Each node may have any number of children, but three is a common limit.

You can then iterate over the tree recursively to compute the result.

An expression node may have an expression node as a child. This would mean that the subexpression node would be recursively evaluated and its result used in the computation of the current node.

Some nodes are just constant nodes, so would be simple to evaluate.

The parser could insert functions and variable writes to a hash table as you specified.

Is this homework? :)
0
 

Author Comment

by:Shooter19
ID: 8183380
If you have any other advice or resources I can use to start this project. Please feel free to drop me a line.
Thanks
0
 
LVL 8

Expert Comment

by:adg080898
ID: 8185264
Flex man page (lexical analyzer generator that generates source code for matching numbers, identifiers, delimiters, whitespace, quoting, etc.):
http://nodevice.com/sections/ManIndex/man0380.html

Complete tutorial you are probably searching for:
http://epaperpress.com/lexandyacc/

I tried to find a good bison man page, but I'm sure you'll find one once you read the tutorial.

Remember these:
"flex" is a "lex" clone
"bison" is a "yacc" clone

Flex handles matching like numbers, whitespace, names, or almost anything you can express with a regular expression.

Bison creates a super fast parser by generating lookup tables for every possible case that the parser may be in, handling precidence and parsing extremely well.

The bison code will call C code that generates data structures (a tree) that represents the entire input.

Once you have parsed the input, and inserted variables and functions into the hash table, it is simple to lookup functions and variables in the hash table and recursively evaluate its nodes to get results. You would be making an interpreter.

Once you get into it, you realize that you want to handle multiple types, but that complicates thing somewhat.

It is very simple to implement the calculator you mentioned, but mentioning the use of the hash table makes it sound more like a compiler.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:Shooter19
ID: 8193142
Thanks for your help. But I still find it hard to understand the assignment yet alone the whole concept of hash tables, and Lex Analysis.
0
 
LVL 8

Expert Comment

by:adg080898
ID: 8201057
A hash table is a very simple concept. Say you have a list of 100 names, and you are going to be doing a LOT of lookups. A poor way to do the search would be to just loop through them all. You need a way to quickly get "close" to the one you need.

There are many types of hash tables, but you specified "open addressing" so I will restrict my comments to that type. (This scheme is not one of the "good" ones, but it is simple).

A hash table needs a "hash function". The hash function "guesses" where the name would be in the hash table based on what you are looking for.

Here is an example of a (really simple) hash function, just add up the ASCII values of each character (A=65, B=66, etc.).

Say my variable name is "MYVAR"

M = 77
Y = 89
V = 86
A = 65
R = 82

77+89+86+65+82=399

Say you picked a hash table size of 256. (It might be better to choose a prime number for the size, like 251). You divide by the size of the hash table and take the remainder and that's your guess:

399 % 256 = 143

So you look at hash entry 143 and see if it is MYVAR. If it is not MYVAR, try 144, if it is not MYVAR, try 145, etc.

Your search stops when you hit an empty entry, when you have searched the whole hash table, and obviously when find the entry you want.

Insertion into the hash table is the same, except you do the search above, and you USE the first empty entry you find to store the value.
0
 

Author Comment

by:Shooter19
ID: 8243919
Here is what I have done so far for creating the hash table from code I found in books and on the net. Tell if I am on the right track. If not can you please just comment in on what changes need to be made
Thanks
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <string.h>

char input;
char y;

int main()
{
     printf("What is the expression you want to enter:\n");
     scanf("%f",&input);
   
}

//creating a hash table

typedef struct hashtable {
     
     int keyentry; //key for hash function
     void *vacated;
     double (*h1)(const void *key);
     double (*h2)(const void *key);
     //error here
     //int (*match)(const void *key1)(const void *key2);
     int hashsize;
     void **table;
     int i; //to be declared for insert
}

//before the main method


double hashtable_init (hastable *htbl,int keyentry, double (*h1)(const void *key),
        double (*h2)(const void *key),
        double (*match)(const void *key1,(const void *key2));
//Allocating space for hash table
    //position counter
     int i;

if ((htbl->table = (void **)malloc(keyentry *sizeof(void *))) == NULL)
    return -1;
//Initialize each position

htbl->keyentry = keyentry;
for ( i= 0; i < htbl->keyentry; i++) {
     htbl->table[i] = NULL;
     htbl->vacated = $vacated;
   
     htbl->h1 = h1;
    htbl->h2 = h2;
     htbl->match = match;
     htbl->hashsize = 0;
     return 0
}

//function declarations
double hashtable_insert(hashtable *htbl , const void *data);
double hashtable_search(const hashtable, void **data);



double hashtable_insert (hashtable *htbl, const void *data)
{
     int i; //index counter for loop
     int position; //for the location in table

if (htbl->size == htbl->keyentry)
     return -1;

temp = (void*)data;

if (hashtable_search(htbl, &tempvar) == 0)
     return -1
     
     for ( i= 0; i < htbl->keyentry; i++) {
          //hashfuction modular math
          position = (htbl->h1(data) + (i * htbl->h2(data))) % htbl->keyentry;
     
          if (htbl->table[position] == NULL || htbl->table[position] ==
              htbl->vacated) {

               htbl->table[position] = (void *)data;
               htbl->hashsize++;
               return 0;
          }
     }

     return -1;
}

double hashtable_search(const hashtable, void **data) {
     int position;
     int i;
     
          for ( i= 0; i < htbl->keyentry; i++) {
          //hashfuction modular math
     position = (htbl->h1(*data) + (i * htbl->h2(*data))) % htbl->keyentry;
     
     if (htbl->table[position] == NULL) {
               return -1;
          }
     else if (htbl->match(htbl->table[position],*data)) {
               *data = htbl->table[position]    
               return 0;
          }
}
0
 
LVL 8

Expert Comment

by:adg080898
ID: 8283832
Your code has many errors.

- missing semicolon on superflous typedef

added type name in proper place and a semicolon.

typedef struct {
    int keyentry; //key for hash function (the number of entries in the table)
    void *vacated;
    double (*h1)(const void *key);
    double (*h2)(const void *key);
    //error corrected here
    int (*match)(const void *key1, const void *key2);
    int hashsize;
    void **table;
    int i; //to be declared for insert
} hashtable;

Your function pointer declarations are wrong, see the correction.

What is $vacated?

Why are you using double everywhere? Your search is by name. You need a structure that stores the name (null terminated string) and the value (which would be a double). The hash table is indexed by name. Read my previous post which explains "open addressing" hash table.

The scanf is completely wrong. It specifies that it wants a float, and then tells scanf to put it into a char (1-byte storage space).

You need to scan in a line at a time. You should probably use fgets(stdin, _buf_, _bufsize_).

The reason you are using the hash table is to store variables. You insert into the hash table when you assign. So if your program gets "myvar = 2 * 2" then it will evaluate 2*2 and store it in the hash table with the name "myvar" and the value 4.0

If someone then says "othervar = myvar + 1" then it will lookup myvar in the hash table, retrieve (the 4.0 stored there), use that to evaluate 4.0 + 1, which gives 5.0, then store 5.0 in the hash table under the name "othervar".

Assignments don't always create a new hash entry. An entry with the same name would be overwritten.

You need to concentrate on parsing the expression with proper order of operations.

atof converts a number to float

strchr is good for searching for characters, like detecting + - * /

You need to implement a stack or use recursion to evaluate in the correct order.

The = operator will write to the hash table.

Names encountered will trigger a hash table lookup to retrieve the value stored under that name.
0
 

Author Comment

by:Shooter19
ID: 8289683
Thanks I'm sorry I forgot to get you the clean code I have so far. Can you please take a close look at my hash function and tell if it makes sense. I have also started working on the parser however, I am finding it difficult to evaluate both the multiplication and division. I have the parser below the hash table code.

#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>

#define M 101
#define EmptyKey 0

char input;

//define structure of the hash table
typedef char KeyType;
typedef char Value;
//typedef int Table[];


//Is this the write definition
typedef struct{
      Value Infotype;
}InfoType;

typedef struct{
    KeyType   Key;
     InfoType  Info;
}TableEntry;


typedef TableEntry Table[M];


//Assigning all values in the table to zero
hashtable_init(Table T){
     int i;
     for (i=0;i<M;++i){
     //has function here maybe
     T[i].Key = EmptyKey;
     }
}


//Write a hashfuction



//Alternative hashFunction
/*
int HashFunc(const void *key1){
const char  *ptr;
int  val;

val=0;
ptr=key1;

  while (*ptr != '\0'){
  int tmp;
  //val
*/
int h(char *str){
   int hashval;
   int i;
   hashval = 0;
   for (i=0;str[i]!=0;i++)
      hashval = 37*hashval + str[i];
   if (hashval < 0) hashval = -hashval;
   return hashval % M;
}

int main ()
{
     printf("Please enter an expression");
          scanf("%f", &input);
}


//Functions Insert and Search

void HashInsert(KeyType K,InfoType I)
{
     int i; //index counter for loop
     int ProbeDecrement; //for the location in table
     
    //i=hashval;
     //i=h(char *str);
     //i=h(k);
     ProbeDecrement=p(k);

     while(T[i].Key != EmptyKey){
          i-=ProbeDecrement;
          if(i<0){
               i+=M;
          }
     
     T[i].Key=K;
     T[i].Info=I;
     }
 
int HashSearch(KeyType K)
{
     int   i;
     int   ProbeDecrement;
     KeyType   ProbeKey;
     
       
     i=h(char *str);
     //i=h(k);
     ProbeDecrement=p(k);      
     ProbeKey = T[i].Key;
     
     while ((K != ProbeKey) && (ProbeKey != EmptyKey)){
               i-=ProbeDecrement;
               if (i<0){
                     i+=M;
               }
               ProbeKey=T[i].Key;
     }

     if(ProbeKey == EmptyKey){
          return -1;
     }
     else {
          return i;
     }


//Parser code so far
#include <stdio.h>
#include <string.h>
char *s;
int k;

main()
{
printf("%d",parse("(1+-3-2)"));
getchar();
}

int parse(char *s2)
{
s=s2;
return parseE();
}

int parseE()
{

int t=parseT();
if ((*s)=='+')
{
s++;
//printf("s=%s\n",s);
return(t+parseE());
}
if ((*s)=='-')
{
*s++;

return (t-parseE());
}
return t;
}

int parseT()
{

int t=0;
if ((*s)=='(')
{
*s++;
t=parseE();
if((*s++)!=')')
{
printf("error");
}
return t;
}
if ((*s)=='-')
{
*s++;
t=parseT();
return -t;
}
while((*s)>='0' && (*s)<='9')
{
t=(10*t);
if ((*s)=='1'), t +=1;
if ((*s)=='2'), t +=2;
if ((*s)=='3'), t +=3;
if ((*s)=='4'), t +=4;
if ((*s)=='5'), t +=5;
if ((*s)=='6'), t +=6;
if ((*s)=='7'), t +=7;
if ((*s)=='8'), t +=8;
if ((*s)=='9'), t +=9;
//printf("t=%d\n",t);
*++s;
//printf("s end =%s\n",s);
}
return t;
}
0
 
LVL 8

Expert Comment

by:adg080898
ID: 8298152
Parts are wrong because of the following requirements quoted from above:

-------

  For example, some assignments given to the parser might be

  x = 1*2*3*4*5-5*-4*-3*-2*-1

  y = 1.11 + 2.22 + -3.33 * 4.4444444

  z = max(x,y,x*y,x+y,x/y)

  quitealongvariablename = sin(cos(sin(cos(2))))

-------

Your hash table has to store long names. A simple method is to use a structure for each hash table entry.

A really simple way to do it is to have an array for the hash table. Each entry of the hash table is a structure.

-----

typedef struct {
    char *pName;
    double dValue;
} KeyType;

KeyType *pVars;    // Array of KeyType structures
int nVarsSize;     // Number of structures allocated

-----

Then somewhere you allocate an array of entries. It appears you are allowing for 101 entries. The hash function you have chosen looks ok.

-----

// Create new hash table (discards current hash table, if any)
int CreateVarTable(int nMaxEntries)
{
    if (pVars)
        free(pVars);
    pVars = malloc(nMaxEntries * sizeof(*pVars));
    if (!pVars)
        return 0;
    nVarsSize = nMaxEntries;

    // Clear the hash table
    memset(pVars, 0, sizeof(*pVars) * nMaxEntries);
}

-----

Your initial requirement was that it used an open-addressing method. I already explained it (03/25/2003) above.

-----

int WriteVar(char *pName, double dValue)
{
    int i, nStepcount;

    // Hash function determines
    nStepcount = 0;
    i = HashFunc(pName);
    do {
        if (pVars[i].pName) {
            // This entry is in use
            if (strcmp(pVars[i].pName, pName) == 0) {
                // Found entry, overwrite
                pVars[i].dValue = dValue;
                break;
            }
        } else {
            // Found open entry, use it
            // NOTE: strdup uses malloc to copy name
            pVars[i].pName = strdup(pName);
            pVars[i].dValue = dValue;
            break;
        }

        // Step to next entry and wrap around
        if (++i >= nVarsSize)
            i = 0;
    } while (++nStepCount <= nVarsSize);

    // Return true if table is not full
    return nStepCount <= nVarsSize;
}

-----

Looking back over your code, I notice the following:

You only seem to be complicating matters with the KeyType, InfoType, TableEntry, EmptyKey. Its hard to tell which are constants, types, and values.

This line is wrong:
  typedef TableEntry Table[M];

Remove the typedef.

KeyType should be a char *, not a char.

For the parser, use atof to parse numbers. Or better use strtod.
0
 

Author Comment

by:Shooter19
ID: 8323336
Thanks for your help. My hash table and parser seems to be working. However, I am stuck on one spot. Say for instance
I have an expression
abc = 5 + 12
How would extract "abc" before the equal sign. As well as
how would extract the value "string" after the equal sign.
x = string*(1 * 2)
Is there anyway you can give me a simple code to figure out this problem. Your help would be greatly appreciated.

Thanks
0
 
LVL 8

Expert Comment

by:adg080898
ID: 8325280
The perfect function for that purpose (that is in the standard C library) is the strtok function.

strtok: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_strtok.2c_.wcstok.2c_._mbstok.asp

Here is (an untested) function that should extract the offset and length of the first name.



-----

// Returns true if a name was found
// Modifies pnOfs and pnLen to offset and length of name
// Skips leading spaces and symbols
int FindName(char *pExpr, int *pnOfs, int *pnLen)
{
    char *pWork, *pOfs;
    int nOfs;

    // Make work copy of string because strtok modifies
    pWork = strdup(pExpr);
    if (!pWork)
        return 0; // Out of memory

    // Return pointer to first non-delimiter and null
    // terminate ON TOP of the first following delimiter
    pOfs = strtok(pWork, " +-*/()");
    if (!pOfs)
        return 0; // No name

    // Calculate offset and length of name
    *pnOfs pOfs - pWork;
    *pnLen = strlen(pWork) - nOfs;
    free(pWork);

    return 1;
}
0
 
LVL 8

Expert Comment

by:adg080898
ID: 8325298
Correction (fixed memory leak):

// Returns true if a name was found
// Modifies pnOfs and pnLen to offset and length of name
// Skips leading spaces and symbols
int FindName(char *pExpr, int *pnOfs, int *pnLen)
{
   char *pWork, *pOfs;
   int nOfs;

   // Make work copy of string because strtok modifies
   pWork = strdup(pExpr);
   if (!pWork)
       return 0; // Out of memory

   // Return pointer to first non-delimiter and null
   // terminate ON TOP of the first following delimiter
   pOfs = strtok(pWork, " +-*/()");
   if (!pOfs) {
       free(pWork);
       return 0; // No name
   }

   // Calculate offset and length of name
   *pnOfs pOfs - pWork;
   *pnLen = strlen(pWork) - nOfs;
   free(pWork);

   return 1;
}
0
 

Author Comment

by:Shooter19
ID: 8338038
I am going to send you bth my parser and hashtable run them separately and see what you think. I tried what you gave me earlier however I still can't extract that string. Can you please take a look at my code nd telling where to the place the above function.  In the hashtable I just assigned an a certain value to "iput" to see what it wold do. It seems to store it in the hashtable and return back the value. The parser does all the calculations that are specified. If you run the parser seaprately it works 100%.
Your help again would be greatly apprecited again. I really need your help. Here are the files

Here is the hashtable part
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define MAXL 8196
char gs[MAXL];
char *cp;
char *errorp;
double oldval;

/************************** HASHTABLE BEGIN ********************/
#define M 101
#define EmptyKey 0
void Hinit();
char input;
double Value;

typedef int KeyType;
typedef double InfoType;

typedef struct{
   KeyType Key;
   InfoType Info;
}TableEntry;

typedef TableEntry Table[M];
Table T;

//Assigning all values in the table to zero
void Hinit()
{
   int i;
   for (i=0;i<M;++i){
   //has function here maybe

    T[i].Key=EmptyKey;
    //printf("this is a test %f",T[i].Key);
   }
}


int PFunc(KeyType K)
{
return 1;
}

int HFunc(KeyType K){
int hashval;
int i;
  hashval = 0;
   printf("test");
//getchar();
//for (i=0;K[i]!=0;i++)
     hashval = 101*hashval + K;
  if (hashval < 0) hashval = -(hashval);
  printf("key = %d",hashval % M);
// getchar();
  return hashval % M;
}


//Functions Insert and Search

void HashInsert(KeyType K,InfoType I)
{
    int i; //index counter for loop
    int ProbeDecrement; //for the location in table

   //i=hashval;
    i=HFunc(K);
    //i=h(k);
    ProbeDecrement=PFunc(K);
    //printf("this is a test of insert fuction  i=%d I=%f ",i,I);
    while(T[i].Key != EmptyKey){
         //printf("this is a test of insert fuction not empty i=%d I=%f
\n",i,I);
         i-=ProbeDecrement;
         if(i<0){
              i+=M;
         }
        }
    //printf("b4 storing %f\n",I);
    T[i].Key=K;
    T[i].Info=I;
    //printf("this is in table %s\n",T[i].Key);
    //printf("this is in table %f\n",T[i].Info);
   // getchar();

}
double HashSearch(KeyType K)
{
    int   i;
    int   ProbeDecrement;
    KeyType   ProbeKey;


    i=HFunc(K);
    //i=h(k);
    ProbeDecrement=PFunc(K);
    ProbeKey = T[i].Key;
   // printf("this is a test of search fuction  i=%d probekey=%s
",i,ProbeKey);
    while ((K != ProbeKey) && (ProbeKey != EmptyKey)){
              i-=ProbeDecrement;
              if (i<0){
                    i+=M;
              }
              ProbeKey=T[i].Key;
    }

    if(ProbeKey == EmptyKey){
         return -1;
    }
    else {
         return T[i].Info;
    }
}
/***************************** HASHTABLE END *********************/

//Here is where the parser starts

/* local prototypes: */
int calcu();
int evaluate(char *line, double *prev_result);

/* Description: */
/* calcu() sets up a string which is then evaluated as an expression  */
/* If (argc>1) main sets up string for evaluate() and prints result.  */

int nextchar()
{
    ++cp;
    while (*cp == ' ')
        ++cp;
    return *cp;
}


int eatspace()
{
    while (*cp == ' ')
        ++cp;
    return *cp;
}


int main()
{
    FILE *ifil;
    char line[100];
      char rest[100];
      char *lineptr;
    int rpos,i,j,k,x;
    double r;
      char word[100];
      j=0;
      i=0;
      k=0;
      //int equate=0;  // 0 if no equal 1 if there is equal

    ifil = stdin;
    while (1) {
        errorp = NULL;
        printf("Calc:");
        if (!(fgets(line, MAXL, ifil)))
            break;
        if (strlen(line) && strncmp(line,"QUIT",4)&& strcmp(line,"Q\n"))
                  {
                  printf("testcal1 line %s",line);
;                    x=(strlen(line));
                for(i=0;i<x;i++)
                        if(line[i] == '=')
                              {
                              for (j=0;j<i;j++){
                                    word[j]=line[j];
                                    printf("rest =  %s",word[j]);}
                              for (j=i+1;j>x;j++){
                                    rest[k]=line[j];
                                    printf("rest =  %s",rest[k]);
                                    k++;}
                              strcat(rest, "\n");
                              //lineptr=line[i];
                              printf("string %s",rest);
                              rpos = evaluate(rest, &r);
                              //HashInsert(word[i],r);
                              }

              rpos = evaluate(line, &r);

            }
        else
            break;
        if (!rpos) {
            printf("%-18g\n", r);
            oldval = r;
        } else {                /* prints Error in field min. 12 wide */
            printf("%*s\n", rpos, "^Error");
        }
    }
    return rpos;                /* if interactive rpos should always be 0 */
}


/*local prototypes.*/
double expression();
double product();
double potens();
double signedfactor();
double factor();
double stdfunc();


int evaluate(char *s, double *r)
{
    cp = s;
    eatspace();
    *r = expression();
    eatspace();
    if (*cp == '\n' && !errorp)
        return (0);
    else
        return (cp - s) + 11;
}


double expression()
{
    double e;
    int opera2;

    /* printf("test arg:%s\n",cp); */

    e = product();
    while ((opera2 = *cp) == '+' || opera2 == '-') {
        nextchar();
        if (opera2 == '+')
            e += product();
        else
            e -= product();
    }
    eatspace();
    return e;
}


double product()
{
    double dp;
    int ope;

    dp = potens();
    while ((ope = *cp) == '*' || ope == '/') {
        nextchar();
        if (ope == '*')
            dp *= potens();
        else
            dp /= potens();
    }
    eatspace();
    return dp;
}


double potens()
{
    double dpo;

    dpo = signedfactor();
    while (*cp == '^') {
        nextchar();
        dpo = exp(log(dpo) * signedfactor());
    }
    eatspace();
    return dpo;
}


double signedfactor()
{
    double ds;
    if (*cp == '-') {
        nextchar();
        ds = -factor();
    } else
        ds = factor();
    eatspace();
    return ds;
}


double factor()
{
    double df;
      double df1;

    switch (*cp) {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
        df = strtod(cp, &cp);
        break;
    case '(':
        nextchar();
        df = expression();
            if (*cp==',')
                  {
                        while (*cp==',')
                              {
                                    nextchar();
                                    df1=expression();
                                    if(df<df1)
                                          df=df1;
                              }
                  }
        if (*cp == ')')
            nextchar();
        else
            errorp = cp;
        break;
    case 'X':
        nextchar();
        df = oldval;
        break;

    default:
        df = stdfunc();
    }

    eatspace();
    return df;
}


char *functionname[] =
{
    "abs", "sin", "cos", "max","\0"
};

double stdfunc()
{
    double dsf;
    char **fnptr;
    int jj;

    eatspace();
    jj = 0;
    fnptr = functionname;
    while (**fnptr) {
        if (strncmp(*fnptr, cp, strlen(*fnptr)) == 0)
            break;

        ++fnptr;
        ++jj;
    }
    if (!**fnptr) {
        errorp = cp;
        return 1;
    }
    cp += (strlen(*fnptr) - 1);
    nextchar();
    dsf = factor();
    switch (jj) {
    case 0: dsf = abs(dsf);  break;
    case 1: dsf = sin(dsf);  break;
    case 2: dsf = cos(dsf);  break;
      case 3: break;
    default:{
            errorp = cp;
            return 4;
        }
    }
    eatspace();
    return dsf;
}


/* end calcu.c */








0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
When we want to run, execute or repeat a statement multiple times, a loop is necessary. This article covers the two types of loops in Python: the while loop and the for loop.
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
Progress
Suggested Courses

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question