【散分】计算器完成!基本表达式都能算,公布源码:)
程序代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#include<math.h>
/*将中缀表达式转化为后缀表达式需要的数据结构*/
struct stackNode {
char data;
struct stackNode *nextPtr;
};
/*中缀转后缀*/
typedef struct stackNode StackNode;
typedef StackNode *StackNodePtr;
void luanlai(StackNodePtr *topPtr , char infix[],int j,char postfix[]) ;
void convertToPostfix(char infix[], char postfix[]);/*中缀转后缀主函数*/
int isOperator (char c);
int isNumber (char c);
int precedence (char operator1, char operator2); /*比较两个表达式的优先级*/
void push(StackNodePtr *topPtr, char value); /*将运算符压入堆栈 后进先出--中缀转后缀时所用*/
char pop (StackNodePtr *topPtr); /*将运算符弹出堆栈 后进先出--中缀转后缀时所用*/
int isEmpty (StackNodePtr topPtr);
// void printStack(StackNodePtr topPtr);
void pushNum(StackNodePtr *head, StackNodePtr *tailer, char value); /*将数字以char形式要入队列先进先出--中缀转后缀时所用*/
int popNum(StackNodePtr *head, StackNodePtr *tailer);/*将数字以int\char形式要入队列先进先出--中缀转后缀时所用*/
void printArray ( char a[]); /*打印数列*/
/*后缀表达式计算需要的数据结构*/
struct stackPostfix {
double data;
struct stackPostfix *nextPtr;
};
/*计算后缀*/
typedef struct stackPostfix StackPostfix;
typedef StackPostfix * StackPostfixPtr;
void pushPostfix(StackPostfixPtr *headPtr, double value);
double popPostfix(StackPostfixPtr *headPtr );
double evaluatePostfixExpression ( char a[]);
double calculate ( double op1 , double op2 , char operate);
void print(StackPostfixPtr headPtr); //打印堆栈
int main(void)
{
// char infix[1001]={'\0'},postfix[1001]={'\0'};
while(1)
{ //begin while
char infix[1001]={'\0'},postfix[1001]={'\0'};
printf("输入:");
gets(infix);
convertToPostfix( infix, postfix); //转换成逆波兰表达式
// printArray (postfix); 输出逆波兰表达式
printf("\n结果: %lf\n",evaluatePostfixExpression(postfix)); //计算逆波兰表达式并返回最终之
printf("\n\n");
}//end while
return 0;
}
void convertToPostfix(char infix[], char postfix[])
{
int i; /*infix末尾添加字符计数*/
int j;
StackNodePtr head=NULL; /*为记录数字链表所用,队列先进先出*/
StackNodePtr tailer=NULL; /*为记录数字链表所用,队列先进先出*/
StackNodePtr topPtr=NULL; /*堆栈,后进先出*/
char forPop[2]={0}; /*为复制堆栈所用*/
char forPopNum[2]={0}; /*为复制数字所用*/
for(i = 0; infix[i]!='\0' ; i++); /*将i移动到数组末尾*/
infix[i]=')';
infix[i+1] = '\0'; /*末尾添加) */
push(&topPtr,'(');
for (j=0; infix[j]!='\0'; j++)
{
/*如果是数字,就压入pushNum队列*/
if(isNumber(infix[j]))
pushNum(&head, &tailer, infix[j]);
/*如果是左括号,就将括号压入push堆栈,
并且在pushNum压入一个0,
确保如果是一个负数,这个负数前面有数字可减,
如果是一个正数,那么可以和任何数结合不改变大小
*/
else if(infix[j]=='(')
{
push(&topPtr,'(');
pushNum(&head,&tailer,'0');
}
/*
如果是运算符:1、首先弹出popNum队列,并且复制到postfix,循环直到队列结束。如果是负号,+ 0
2、(luanlai ()函数执行 )比较优先级,如果栈顶优先级高于当前,弹出push,复制到postfix中,否则,把弹出的运算符弹入push
3、把运算符压入pop中
*/
else if(isOperator(infix[j]))
{
while(head != NULL)
{
forPopNum[0] = popNum(&head,&tailer);
forPopNum[1] = '\0';
strcat( postfix,forPopNum );
}
strcat( postfix," "); /*压入空格*/
luanlai(&topPtr , infix,j,postfix) ;
push(&topPtr, infix[j]); /*将运算符压入堆栈*/
}
/*
如果是右括号:1、首先弹出popNum队列,并且复制到postfix,循环直到队列结束,压入空格
2、弹出运算符,复制到postfix,压入空格,直到一个左括号
3、将左括号弹出堆栈
*/
else if(infix[j]==')')
{
while(head!=NULL)
{
forPopNum[0] = popNum(&head,&tailer);
forPopNum[1] = '\0';
strcat( postfix,forPopNum);
}
strcat( postfix," ");
while( (forPop[0] = pop(&topPtr) )!= '(')
{
forPop[1]='\0';
strcat( postfix,forPop );
strcat( postfix," " );
}
}
}
}
int isOperator (char c)
{
if ( c == 43 || c == 45 || c == 42 || c == 47 || c == 94 || c == 37 )
return 1;
else
return 0;
}
int isNumber (char c)
{
if( isdigit(c) ||c==46 )
return 1;
else
return 0;
}
/*判断操作符优先级;
首先判断operator是什么运算符;
给相应的one或者two 赋值;
返回two - one 即 堆栈 - 数组中 运算符;
如果堆栈运算符优先级高于或者等于分别返回1和0,低于返回-1;
*/
int precedence (char operator1, char operator2)
{
int i;
int temp[2][2]={{operator1, operator2},{0}};
for(i = 0;i<2 ; i ++)
{
switch (temp[0][i])
{
case 43:
case 45:
temp[1][i]=1;
break;
case 42:
case 47:
case 94:
case 37:
temp[1][i]=2;
break;
case 40:
case 41:
temp[1][i]=-1;
break;
}
}
return temp[1][1]-temp[1][0];
}
/*后进先出堆栈*/
void push(StackNodePtr *topPtr, char value)
{
StackNodePtr newPtr;
if( (newPtr=(StackNodePtr) malloc (sizeof( struct stackNode) ) )!= NULL)
{
newPtr->data=value;
newPtr->nextPtr=NULL;
if( *topPtr ==NULL)
{
*topPtr=newPtr;
}
else
{
newPtr->nextPtr=*topPtr;
*topPtr=newPtr;
}
}
else
{
printf("NOT ENOUGH MEMORY\n");
}
}
char pop (StackNodePtr *topPtr)
{
StackNodePtr tempPtr;
char value;
if(*topPtr ==NULL)
{
printf("EMPTY\n");
return;
}
else
{
tempPtr = (*topPtr);
value= tempPtr->data;
(*topPtr)=(*topPtr)->nextPtr;
free(tempPtr);
return value;
}
}
void pushNum(StackNodePtr *head, StackNodePtr *tailer, char value)
{
StackNodePtr newPtr;
if( (newPtr=(StackNodePtr) malloc (sizeof( struct stackNode) ) )!= NULL)
{
newPtr->data=value;
newPtr->nextPtr=NULL;
if( *head==NULL)
{
(*head) = newPtr;
}
else
{
(*tailer)->nextPtr= newPtr;
}
(*tailer)= newPtr;
}
}
int popNum(StackNodePtr *head, StackNodePtr *tailer)
{
int value;
StackNodePtr tempPtr;
if( head !=NULL)
{
value = (*head)->data;
tempPtr = *head;
*head = (*head)->nextPtr;
free(tempPtr);
if(*head ==NULL)
*tailer=NULL;
return value;
}
}
int isEmpty (StackNodePtr topPtr)
{
if (topPtr==NULL)
return 1;
else
return 0;
}
void printArray ( char a[])
{
int i;
for (i=0; a[i]!='\0'; i++ )
printf("%c", a[i]);
}
double evaluatePostfixExpression ( char a[])
{
char b[]=" "; /*strtoken的条件*/
char *token;
StackPostfixPtr headPtr=NULL;
double x=0.00;
double y=0.00;
token = strtok( a, b);
while (token != NULL)
{
if(isNumber( *token ) )
{
pushPostfix( &headPtr, atof(token) );
}
else
{
x=popPostfix( &headPtr );
y=popPostfix( &headPtr );
pushPostfix(&headPtr,calculate( x , y , (*token) ) );
}
token =strtok (NULL , b);
}
return popPostfix(&headPtr);
}
void pushPostfix(StackPostfixPtr *headPtr, double value)
{
StackPostfixPtr newPtr;
if( (newPtr=(StackPostfixPtr) malloc (sizeof( struct stackPostfix) ) )!= NULL)
{
newPtr->data=value;
newPtr->nextPtr= *headPtr;
*headPtr = newPtr;
}
else
{
printf("NOT ENOUGH MEMORY\n");
}
}
double popPostfix(StackPostfixPtr *headPtr )
{
StackPostfixPtr tempPtr;
double value;
if( (*headPtr) ==NULL)
{
return 0;
}
else
{
tempPtr = (*headPtr);
value= tempPtr->data;
(*headPtr)=(*headPtr)->nextPtr;
free(tempPtr);
return value;
}
}
double calculate ( double op1 , double op2 , char operate)
{
switch (operate)
{
case 43:
return op1+op2;
case 45:
return op2-op1;
case 42:
return op2*op1;
case 47:
return (double)op2/op1;
case 94:
return pow(op2,op1);
case 37:
return (int)(op2)%(int)(op1);
}
return 0;
}
void luanlai(StackNodePtr *topPtr , char infix[],int j,char postfix[])
{
char forPop[2]={'\0'};
forPop[0] = pop(topPtr);
forPop[1]='\0';
if( (precedence(infix[j], forPop[0]))==1 || (precedence(infix[j], forPop[0]))==0)
{
strcat( postfix,forPop );
strcat( postfix," ");
/*压入空格*/
luanlai(topPtr , infix,j,postfix) ;
}
else
push( topPtr, forPop[0]);
}
void print(StackPostfixPtr headPtr)
{
if(headPtr ==NULL)
{
printf("empty");
}
else
{
printf("\nthe stack is:\n");
while(headPtr !=NULL)
{
printf( "%lf-->", headPtr->data);
headPtr=headPtr->nextPtr;
}
}
printf("NULL\n\n");
}









