Linux系統下用C語言實現浮點數四則運算表達式的求值

Linux系統下用C語言實現浮點數四則運算表達式的求值

 

實現功能:

1. 支持任意長度四則運算表達式,允許的操作符是:"+","-","*","/","(",")",以“#”或“=”結束表達式的輸入
2. 操作數是浮點數,可以小數形式或指數形式表示,如123.456和1.23456E2兩種表示形式
3. C語言實現,在linux平臺上運行,也可以在Cygwin上運行
4. 用命令行方式輸入操作符和操作數

5.共兩個文件:頭文件和源代碼文件

 

文件1: EvaluateExpression.c

-----------------------FILE: EvaluateExpression.c BEGIN--------------------------------------------------

/**
* File Name:           EvaluateExpression.c
* Description:         This file implements the function of the basic arithmetic calculations.
*                           All valid/acceptable operations are only addition,subtraction,multiplication,division.
*                           The valid operators are defined as {'+', '-', '*', '/', '(', ')', '#'}.
*                           The '#' sign is defined as the ending symbol of experession input.
*                           And it surpports the float oprand type only now.
*
* Author:                Sean.Wang
* Contact Mail:        [email protected]
* Completed Date:  July 05, 2009
**/

#include "EvaluateExpression.h"

int main ( void )
{
        float result = 0.0F;

        printf ( "/nPlease enter an expression to evaluate,and ends with the pound sign:/n" );
        result = ( float ) FloatEvaluateExpression();
        printf ( "Its result:%f/n", result );
        return 0;
}


/**
* Function Name:  FloatEvaluateExpression(void)
* Description: Implementing the float operations of addition,subtraction,multiplication,division.
* Arguments: void
* Returns: float
**/
float FloatEvaluateExpression ( void )
{
        STACK *sOPTR = ( STACK * ) malloc ( sizeof ( STACK ) ); /* sOPTR:Operator Stack*/
        STACK *sOPND = ( STACK * ) malloc ( sizeof ( STACK ) ); /* sOPND:Operand Stack*/
        char c = ' ';
        char lastchar = ' ';
        float a = 0.0F;
        float b = 0.0F;
        char theta = ' ';
        float result = 0.0F;
        float valf = 0.0F; /*the float value of the digital string input from STDIN*/
        char strf[MAXLENGTH] = {'/0'}; /*the valid float string input from STDIN*/
        int idx = 0;
        bool pointAvail = TRUE; /*Decimal Point available*/
        bool expAvail = TRUE; /*Exponent available*/

        InitStack ( sOPTR );
        Push ( sOPTR, '#' );
        lastchar = '#';
        InitStack ( sOPND );
        c = getchar();

        while ( c != '#' || ( ( char ) GetTop ( sOPTR ) ) != '#' )
        {
                while ( isspace ( c ) )
                        c = getchar();

                if ( c == '=' )
                        c = '#';

                idx = 0;
                if ( ( c == '-' || c == '+' ) && ( IsOprator ( lastchar ) ) )
                {
                        strf[idx++] = c;
                        c = getchar();
                        if ( ! ( isdigit ( c ) || c == '.' ) )
                        {
                                printf ( "EXIT_FAILURE: format is invalid or undefined,!/n" );
                                exit ( EXIT_FAILURE );
                        }
                }
                strf[idx] = '/0';

                if ( isdigit ( c ) || c == '.' )
                {
                        lastchar = '0';
                        pointAvail = TRUE; /*Decimal Point available*/
                        expAvail = TRUE; /*Exponent available*/

                        do
                        {
                                if ( c == '.' )
                                {
                                        if ( !pointAvail )
                                        {
                                                printf ( "ERROR: Decimal Point not available more than once in a float data!/n" );
                                                return ERROR;
                                        }
                                        else
                                        {
                                                strf[idx++] = c;
                                                pointAvail = FALSE;
                                                continue;
                                        }
                                }

                                if ( c == 'e' || c == 'E' )
                                {
                                        if ( !expAvail )
                                        {
                                                printf ( "ERROR: Exponent s not available more than once in a float data!/n" );
                                                return ERROR;
                                        }
                                        else
                                        {
                                                strf[idx++] = c;
                                                expAvail = FALSE;
                                                c = getchar();
                                                if ( isdigit ( c ) || c=='+' || c=='-' )
                                                        strf[idx++] = c;
                                                else
                                                {
                                                        printf ( "EXIT_FAILURE:'E' or 'e' followed only by digit or '+' or '-'!/n" );
                                                        exit ( EXIT_FAILURE );
                                                }
                                                continue;
                                        }
                                }

                                if ( isdigit ( c ) || c == '.' || c == 'e' || c == 'E' )
                                        strf[idx++] = c;
                                else
                                        break;
                        }
                        while ( ( c = getchar() ) );

                        strf[idx++] = '/0';
                        valf = ConvertFloatValue ( strf );
                        Push ( sOPND, valf );
                }
                else if ( IsOprator ( c ) )
                {
                        lastchar = c;
                        if ( ( sOPTR->top == NULL ) && ( sOPND->top != NULL ) )
                                return Pop ( sOPND );
                        switch ( Precede ( ( char ) GetTop ( sOPTR ), c ) )
                        {
                                case '<' :
                                {
                                        Push ( sOPTR, c );
                                        c = getchar();
                                        break;
                                }
                                case '=' :
                                {
                                        Pop ( sOPTR );
                                        c = getchar();
                                        break;
                                }
                                case '>' :
                                {
                                        theta = ( char ) Pop ( sOPTR );
                                        b = ( float ) Pop ( sOPND );
                                        a = ( float ) Pop ( sOPND );
                                        Push ( sOPND, Operate ( a, theta, b ) );
                                        break;
                                }

                                default: printf ( "ERROR: Please check if this operator or expression format is invalid or undefined!/n" );
                                        return ERROR;

                        }

                }
                else
                {
                        printf ( "ERROR: Please check if this oprands/operators/expression format is invalid or undefined,!/n" );
                        return ERROR;

                }
        }


        result = ( float ) GetTop ( sOPND );

        DestroyStack ( sOPTR );
        DestroyStack ( sOPND );
        free ( sOPTR );
        free ( sOPND );
        return result;

}


/*Basic Operating Functions on stack.*/
/*Initializing a stack*/
STATUS InitStack ( STACK *s )
{
        /*STACK *s = ( STACK * ) malloc ( sizeof ( STACK ) );*/
        if ( s != NULL )
        {
                s->top=NULL;
                return OK;
        }

        printf ( "ERROR:Failed to initialize stack!/n" );
        return ERROR;
}

/*Destroying a stack*/
STATUS DestroyStack ( STACK *s )
{
        STACKNODE *snode=NULL;
        assert ( s != NULL );

        while ( s->top != NULL )
        {
                snode = s->top;
                s->top = s->top->prior;
                free ( snode );
                snode = NULL;
        }

        free ( s );
        s=NULL;
        return OK;
}

/*Push an element in stack*/
STATUS Push ( STACK *s, ELEMTYPE e )
{
        assert ( s != NULL );
        STACKNODE *snode= ( STACKNODE * ) malloc ( sizeof ( STACKNODE ) );
        if ( snode == NULL )
        {
                printf ( "ERROR:Failed to allocate memory for a new stack node!/n" );
                return ERROR;
        }

        snode->data = e;
        snode->prior = s->top;
        s->top = snode;

        return OK;
}

/*Pop the top element out of stack*/
ELEMTYPE Pop ( STACK *s )
{
        STACKNODE *snode = NULL;
        ELEMTYPE e;
        assert ( s != NULL );

        if ( s->top == NULL )
        {
                printf ( "EXIT 0:Invalid to Pop() on empty stack!/n" );
                exit ( EXIT_FAILURE );
        }

        e = s->top->data;
        snode = s->top;
        s->top = s->top->prior;
        free ( snode );
        snode = NULL;

        return e;
}

/*get the top element in the stack*/
ELEMTYPE GetTop ( const STACK *s )
{
        assert ( s != NULL );
        if ( s->top == NULL )
        {
                printf ( "EXIT 0:Failed to GetTop() on empty stack!/n" );
                exit ( EXIT_FAILURE );
        }

        return s->top->data;
}


/*Convert digital string to the float value.*/
float ConvertFloatValue ( const char *str )
{
        assert ( str != NULL );
        float value = 0.0F;
        float integerPart = 0.0F;
        float fractionPart = 0.0F;
        float exponentPart = 1.0F;
        int expSign = POSITIVE; /*Flag sign of the exponent,negative or positive nuber*/
        int valSign = POSITIVE; /*Flag sign of the float value, negative or positive nuber*/
        int exp = 0; /*the exponent of the float value*/
        int n=0;

        while ( *str == ' ' )
                str++;

        if ( *str == '-' )
        {
                valSign = NEGATIVE;
                str++;
        }
        else if ( *str == '+' )
        {
                valSign = POSITIVE;
                str++;
        }
        else
        {
                ;/*null*/
        }

        for ( integerPart = 0.0F; ( str != NULL ) && ( isdigit ( *str ) ); str++ )
        {
                integerPart *= 10;
                integerPart += ( *str-'0' );
        }

        if ( *str == '.' )
        {
                str++;

                for ( fractionPart = 0.0F, n=1; ( ( str != NULL ) && ( isdigit ( *str ) ) ); str++ )
                {
                        fractionPart += ( *str-'0' ) / Power10 ( n++ );
                }

        }

        if ( *str == 'e' || *str == 'E' )
        {
                str++;
                if ( !isdigit ( *str ) )
                {
                        switch ( *str )
                        {
                                case '-':
                                        expSign = NEGATIVE;
                                        str++;
                                        break;
                                case ' ':
                                case '+':
                                        expSign = POSITIVE;
                                        str++;
                                        break;

                                default:
                                        printf ( "ERROR:'E' or 'e' followed by an unacceptable symbol:%c in the float string!/n", *str );
                                        return ERROR;
                        }
                }

                for ( exp = 0, n = 0; ( ( str != NULL ) && ( isdigit ( *str ) ) ); str++ )
                {
                        exp *=10;
                        exp += ( *str-'0' );

                }

                exponentPart = ( float ) Power10 ( expSign*exp );
        }

        value = ( float ) ( valSign * ( integerPart + fractionPart ) * exponentPart );

        return value;
}


/*the operation with the theta operator on oprand a and oprand b*/
float Operate ( float a, char theta, float b )
{
        switch ( theta )
        {
                case '+':
                        return a+b;
                        break;
                case '-':
                        return a-b;
                        break;
                case '*':
                        return a*b;
                        break;
                case '/':
                        if ( b < FLT_EPSILON && b > ( 0 - FLT_EPSILON ) )
                                printf ( "Warring:potentially divide by zero exception./n" );
                        return a/b;
                        break;

                default : printf ( "Warring:It is an unacceptable operations with the %c opertor!/n",theta );
        }

        return ERROR;
}


/*define the priority of the operators*/
char Precede ( char a,char c )
{
        int i,j;
        char b[7][7]=
        {
                {'>', '>', '<', '<', '<', '>', '>'},
                {'>', '>', '<', '<', '<', '>', '>'},
                {'>', '>', '>', '>', '<', '>', '>'},
                {'>', '>', '>', '>', '<', '>', '>'},
                {'<', '<', '<', '<', '<', '=', ' '},
                {'>', '>', '>', '>', ' ', '>', '>'},
                {'<', '<', '<', '<', '<', ' ', '='}
        };

        switch ( a )
        {
                case '+' : i=0;break;
                case '-' : i=1;break;
                case '*' : i=2;break;
                case '/' : i=3;break;
                case '(' : i=4;break;
                case ')' : i=5;break;
                case '#' : i=6;break;

                default:
                        printf ( "ERROR:Oprator %c invalid or unacce!/n", a );
                        break;
        }

        switch ( c )
        {
                case '+' : j=0; break;
                case '-' : j=1; break;
                case '*' : j=2; break;
                case '/' : j=3; break;
                case '(' : j=4; break;
                case ')' : j=5; break;
                case '#' : j=6; break;

                default:
                        printf ( "ERROR:Oprator %c invalid or unacce!/n", c );
                        break;

        }

        switch ( b[i][j] )
        {
                case '>':
                case '<':
                case '=':
                        return b[i][j];

                default: printf ( "ERROR: expression format may be invalid or undefined!/n" );
                        return ERROR;
        }

}

/*verify if c is in the oprator list */
bool IsOprator ( char c )
{
        switch ( c )
        {
                case '+':
                        return TRUE;
                case '-':
                        return TRUE;
                case '*':
                        return TRUE;
                case '/':
                        return TRUE;
                case '#':
                        return TRUE;
                case '(':
                        return TRUE;
                case ')':
                        return TRUE;
                        break;

                default:return FALSE;
        }
        return ERROR;
}

float Power10 ( int n )
{
        float val = 1;
        while ( n>0 )
        {
                val = val * 10;
                n--;
        }
        while ( n<0 )
        {
                val = val / 10;
                n++;
        }
        if ( n == 0 )
                return val;

        return ERROR;
}

-----------------------FILE: EvaluateExpression.c END--------------------------------------------------

 

文件2: EvaluateExpression.h
-----------------------FILE: EvaluateExpression.c BEGIN--------------------------------------------------

#ifndef __EVALUATEEXPRESSION_H__
#define __EVALUATEEXPRESSION_H__

#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include <math.h>
#include <float.h>
#include <stdlib.h>
#include <assert.h>

#define OK 1
#define ERROR 0
#define NEGATIVE -1
#define POSITIVE 1
#define TRUE 1
#define FALSE 0
#define MAXLENGTH 100
/*#define FLT_EPSILON (1E-5)*/

typedef int STATUS;
typedef float ELEMTYPE;
typedef int bool;

typedef struct STACKNODE
{
        ELEMTYPE data;
        struct STACKNODE *prior;
}STACKNODE;

typedef struct STACK
{
        STACKNODE *top;
}STACK;

STATUS InitStack ( STACK *s );
STATUS DestroyStack ( STACK *s );
STATUS Push ( STACK *s, ELEMTYPE e );
ELEMTYPE Pop ( STACK *s );
ELEMTYPE GetTop ( const STACK *s );

float FloatEvaluateExpression ( void );
float ConvertFloatValue ( const char *str );
float Operate ( float a, char theta, float b );
char Precede ( char a,char c );
bool IsOprator ( char c );
float Power10 ( int n );

#endif

-----------------------FILE: EvaluateExpression.c END--------------------------------------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章