Logo Search packages:      
Sourcecode: papaya version File versions  Download package

calcu.c

/* file calcu.c */
/* (c) Donald Axel GPL - license */
/* ANSI - C program demonstration, command line calculator */
/* Recursive descent parser */
/* Improve: Make a HELP command. Add more variables.       */

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

#ifdef WIN32
#define strncasecmp strnicmp
#define strcasecmp stricmp
#endif


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

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

// int res = evaluate(char *, double *)
// if (res)
// printf ("result: %g.\n", double)

/* 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.  */
/* stricmp does not stop at '\n' - so we have to compare with "xx\n"  */
/* gettok() could solve that problem. TRY to use gettok().            */



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


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


int calcu()
{
    FILE *ifil;
    char line[MAXL];
    int rpos = 0;
    double r;

    ifil = stdin;
    while (1) {
        errorp = NULL;
        if (!fgets(line, MAXL, ifil))
            break;
        if (strlen(line) && strncasecmp(line,"QUIT",4)
&& strcasecmp(line,"Q\n"))
            rpos = evaluate(line, &r);
        else
            break;
        if (!rpos) {
            oldval = r;
        } else {                /* prints Error in field min. 12 wide */
            printf("%*s\n", rpos, "^Error");
        }
    }
    return rpos;                /* if interactive rpos should always be 0 */
}


/* More local prototypes. This could, of course, be a separate file. */
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;

    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 == '/' || ope == '\\') {
        nextchar();
        if (ope == '*')
            dp *= potens();
        else if (ope == '/')
            dp /= (int)potens();
      else {
        double result = potens();
        int quotient = (int) dp / result;
        int remainder = dp - (quotient * result);
        dp = (double) remainder;
      }
    }
    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;

    /* while (*cp!='\n') {
       putchar(*cp++);
       } 
     */

    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 == ')')
            nextchar();
        else
            errorp = cp;
        break;
    case 'X':
        nextchar();
        df = oldval;
        break;

    default:
        df = stdfunc();
    }

    eatspace();
    return df;
}


char *functionname[] =
{
    "abs", "sqrt", "sin", "cos", "atan", "log", "exp", "\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 = sqrt(dsf); break;
    case 2: dsf = sin(dsf);  break;
    case 3: dsf = cos(dsf);  break;
    case 4: dsf = atan(dsf); break;
    case 5: dsf = log(dsf);  break;
    case 6: dsf = exp(dsf);  break;
    default:{
            errorp = cp;
            return 4;
        }
    }
    eatspace();
    return dsf;
}


/* end calcu.c */



Generated by  Doxygen 1.6.0   Back to index