| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1066 人关注过本帖
标题:【散分】计算器完成!基本表达式都能算,公布源码:)
只看楼主 加入收藏
oszc
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:111
专家分:154
注 册:2011-4-15
结帖率:100%
收藏
已结贴  问题点数:100 回复次数:15 
【散分】计算器完成!基本表达式都能算,公布源码:)
程序代码:
#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");
}
搜索更多相关主题的帖子: 计算器 表达式 
2011-06-27 15:23
Pirelo
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:118
专家分:550
注 册:2011-1-28
收藏
得分:7 
不错,帮顶!!
2011-06-27 15:28
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:7 
怎么用呢??以后自己写的软件不能没有帮助吧??

My life is brilliant
2011-06-27 15:37
oszc
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:111
专家分:154
注 册:2011-4-15
收藏
得分:0 
抱歉,就是一般计算器那么用,输入:2^2+3 输出7 ,很简单,以后我会注意把用法写上...
2011-06-27 15:46
cosdos
Rank: 9Rank: 9Rank: 9
来 自:ShangHai
等 级:蜘蛛侠
威 望:6
帖 子:2109
专家分:1385
注 册:2007-6-19
收藏
得分:7 
好像过于复杂

—>〉Sun〈<—
2011-06-27 16:11
Toomj
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
帖 子:257
专家分:1826
注 册:2011-5-17
收藏
得分:7 
顶一个
2011-06-27 16:45
loveshuang
Rank: 9Rank: 9Rank: 9
来 自:湖北武汉
等 级:蜘蛛侠
帖 子:270
专家分:1198
注 册:2010-11-14
收藏
得分:7 
       栈的应用。。。顶下。
2011-06-27 17:25
sc19861202
Rank: 2
来 自:唐山
等 级:论坛游民
帖 子:23
专家分:47
注 册:2011-3-19
收藏
得分:7 
顶一下,学习了!!!
2011-06-27 19:05
flyue
Rank: 10Rank: 10Rank: 10
来 自:江南西道
等 级:贵宾
威 望:19
帖 子:3465
专家分:1563
注 册:2006-6-20
收藏
得分:7 
栈式计算器。接分

天之道,损有余而补不足.人之道则不然,损不足以奉有余.孰能有余以奉天下,唯有道者.
2011-06-27 19:55
njkido
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
帖 子:224
专家分:1184
注 册:2011-3-8
收藏
得分:7 
标致
马克
2011-06-27 19:58
快速回复:【散分】计算器完成!基本表达式都能算,公布源码:)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.033175 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved