您的位置:首页 > 运维架构 > Linux

Linux系统下用C语言实现浮点数四则运算表达式的求值

2009-07-24 14:02 633 查看
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: Sean.Gn@gmail.com
* 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--------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: