| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3859 人关注过本帖, 1 人收藏
标题:逆波兰计算器(后缀计算器)
只看楼主 加入收藏
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
结帖率:95.65%
收藏(1)
 问题点数:0 回复次数:15 
逆波兰计算器(后缀计算器)
第一版本。
输入函数是个坑。
先就这样了,以后想到了再来改进输入函数。

有一点小BUG,如果最后的运算符是减号,必须手动加一个空格或者多按一下回车。
这是为了可以进行负数计算。
看来还得继续努力修正这个问题。

程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef double OpType;
void
MakeStack( void );
void
DeleteStack( void );
void 
Push( OpType value );
OpType
Top( void );
int
IsEmpty( void );
int
IsFull( void );
int
GetOperand( void );


int
main( void )
{
    int ch;
    OpType op;

    MakeStack();

    while( EOF != ( ch = GetOperand() ) )
    {
        switch( ch )
        {
            case '+':
                Push( Top() + Top() );
                break;
            case '-':
                op = Top();
                Push(  Top() - op );
                break;
            case '*':
                Push( Top() * Top() );
                break;
            case '/':
                op = Top();
                Push( Top() / op );
                break;
            case '%':
                op = Top();
                Push( ( OpType )( ( int )Top() % ( int )op ) );
                break;
            case '\n':
                if( IsEmpty() )
                    break;
                printf( "%.2lf\n", Top() );
                DeleteStack();
                MakeStack();
                break;
            default:
                break;
        }
    }
    printf( "Bye.\n" );
    DeleteStack();
    
    return 0;
}

#define MAXSIZE 128
#include <ctype.h>

int
GetOperand( void )    
{
    int ch;
    int lx;
    char Temp[ MAXSIZE ];

    for( lx = 0; MAXSIZE - 1 > lx && EOF != ( ch = getchar() ); ++lx )
    {
        if( isdigit( ch ) || '.' == ch )
        {
            if( 0 == lx )
                Temp[ lx++ ] = '0';
            Temp[ lx ] = ch;
        }
        else if( '-' == ch )
        {
            if( 0 == lx )
                Temp[ lx ] = ch;
            else
                break;
        }
        else
            break;
    }

    Temp[ lx ] = '\0';

    if( 1 == strlen( Temp ) && '-' == Temp[ 0 ] )
        return Temp[ 0 ];

    if( 0 < lx )
        Push( atof( Temp ) );

    return ch;
}


#define INITSIZE 128
static OpType *Stack;
static int stacktop = -1;
static int CurrentSize = INITSIZE;


void
MakeStack( void )
{
    Stack = ( OpType * )malloc( CurrentSize * sizeof( OpType ) );
    assert( NULL != Stack );
}


void
DeleteStack( void )
{
    free( Stack );
    Stack = NULL;
    CurrentSize = INITSIZE;
    stacktop = -1;
}


void
Push( OpType value )
{
    assert( !IsFull() );
    Stack[ ++stacktop ] = value;
}


OpType
Top( void )
{
    assert( !IsEmpty() );
    return Stack[ stacktop-- ];
}


int
IsEmpty( void )
{
    return -1 == stacktop;
}


int
IsFull( void )
{
    OpType *Temp;

    if( stacktop == CurrentSize - 1 )
    {
        CurrentSize += INITSIZE;
        Temp = ( OpType * )realloc( Stack, CurrentSize * sizeof( OpType ) );
        if( NULL == Temp )
        {
            CurrentSize -= INITSIZE;
            return 1;
        }
        Stack = Temp;
        return 0;
    }
    else
        return 0;
}


[此贴子已经被作者于2017-4-7 20:58编辑过]

搜索更多相关主题的帖子: 计算器 
2017-04-07 18:18
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
收藏~期待写个中序表达式转化为后序表达式的算法~

还有~什么时候讲到二叉树啊自学了很久进展不大~就是差个删除节点还要弄懂~

[此贴子已经被作者于2017-4-7 18:43编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-04-07 18:41
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 2楼 九转星河
咦……似乎想到一块去了,我下一步正好就准备写一个将中缀转为后缀的计算器。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-07 18:43
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 3楼 renkejun1942
刚刚测试了一波~是我输入数据方法有问题还是什么原因~程序怎么会崩溃~~~~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-04-07 18:50
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 4楼 九转星河
程序会崩溃是安全检查的,那说明你的输入有问题而导致栈为空。

我举个例子。

比如:1 + 2 * 5
你应该写成 1 2 5 * +

另外闲扯一句,中缀转后缀需要学习,我自己测试的时候都经常因为输入问题而崩溃。

[此贴子已经被作者于2017-4-7 18:57编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-07 18:52
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 4楼 九转星河
当然也不排除存在BUG,我只进行了量比较少的测试。
如果你能告诉我你的输入,我想我会容易定位到可能存在的BUG。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-07 18:54
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 5楼 renkejun1942
果然是我输入格式有问题~~~~我还是要去百度一下什么是逆波兰计算~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-04-07 19:18
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 5楼 renkejun1942
减法似乎有些问题~
图片附件: 游客没有浏览图片的权限,请 登录注册


看看这样输入有什么问题~~~

没事了~输入加法时后面跟空格能正常输出~但输入减法就不行了~这个感觉可以完善一下~

[此贴子已经被作者于2017-4-7 19:27编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-04-07 19:25
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 8楼 九转星河
啊啊啊啊,果然是哪里。
你把GetOperand()函数 for()语句中的‘-’ == ch 去掉。然后删除掉if( '-' == ch && 0 != lx )

当时这样写为了可以进行负数计算。
看来负数方面我还得进行修正。

嗯嗯,减法有点小BUG,已经修正了,更新后的代码重新发在主楼。

负数问题,我先想想,先吃饭了。

[此贴子已经被作者于2017-4-7 19:36编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-07 19:32
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
看了代码写了注释~弄懂思路~学习了~原来理解了就很简单~~~

程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef double OpType;   //采取double型计算

void MakeStack( void );  //创建一个栈

void DeleteStack( void );//删除一个栈

void Push( OpType value );//入栈

OpType Top( void );       //出栈
 
int IsEmpty( void );      //判断是否栈空

int IsFull( void );       //判断栈满

int GetOperand( void );   //对数据进行转化


int main( void )
{ 
    int ch;            //运算符暂存变量
    OpType op;         //这个是运算结果保存数据

    MakeStack();       //首先,构建一个栈

    while( EOF != ( ch = GetOperand() ) )  //对数据进行转化处理
    {
        switch( ch )    //对运算符进行处理
        {
            case '+':   //如果是加法出栈并相加并入栈
                Push( Top() + Top() );  
                break; 
            case '-':
                op = Top();   //如果是减法出栈并相减并入栈
                Push( op - Top() );   
                break;
            case '*':         //如果是乘法出栈相乘并入栈
                Push( Top() * Top() );
                break;
            case '/':
                op = Top();  //如果是除法出栈相除并入栈
                Push( Top() / op );
                break;
            case '%':        //如果是求余则出栈求余
                op = Top();
                Push( ( OpType )( ( int )Top() % ( int )op ) );
                break;
            case '\n':   //如果结束输入
                printf( "%.2lf\n", Top() );   //则获取结果
                DeleteStack();                //销毁栈
                MakeStack();                  //重建一个栈
                break;
            default:
                break;
        }
    }
    printf( "Bye.\n" );
    DeleteStack();
    
    return 0;
}

#define MAXSIZE 128
#include <ctype.h>

int GetOperand( void )      
{
    int ch;
    int lx;   //lx代表数据长度
    char Temp[ MAXSIZE ];    

    for( lx = 0; MAXSIZE - 1 > lx && EOF != ( ch = getchar() ) && ( isdigit( ch ) || '.' ==  ch || '-' == ch ); ++lx )    
    {   //如果输入的是非运算符号数据数据
        if( '.' == ch && 0 == lx )   //这里举个例子用.5表示0.5,如果第一位是.则在前面补0
            Temp[ lx++ ] = '0';
        Temp[ lx ] = ch;
    }

    Temp[ lx ] = '\0';              
    if( 0 != lx )
        Push( atof( Temp ) );  //atof是把Temp储存的数据转化为doulbe型保存,这里入栈

    return ch;                 //返回输入的运算符号
}


#define INITSIZE 128      //设栈的最大长度为128
static OpType *Stack;     //申明一个栈指针
static int stacktop = -1; //初始化栈顶指针为-1
static int CurrentSize = INITSIZE;   //这个代表栈的容量


void
MakeStack( void )
{
    assert( NULL == Stack );    //判断输入合法性
    Stack = ( OpType * )malloc( CurrentSize * sizeof( OpType ) );  //创建一个栈
    assert( NULL != Stack );   //判断输入合法性
}


void
DeleteStack( void )
{
    assert( NULL != Stack );   //判断是否异常
    free( Stack );             //释放栈
    Stack = NULL;              //设栈指针为空
    CurrentSize = INITSIZE;    //重置栈容量大小数据
    stacktop = -1;             //重置栈指针
}


void Push( OpType value )
{
    assert( NULL != Stack );      //判断输入合法性
    assert( !IsFull() );          //判断并处理栈满,这里栈用了全局变量保存数据
    Stack[ ++stacktop ] = value;  //入栈
}


OpType Top( void )
{
    assert( NULL != Stack );    //检查数据输入合法性
    assert( !IsEmpty() );       //判断栈是否为空

    return Stack[ stacktop-- ]; //获取栈顶元素
}


int
IsEmpty( void )
{
    return -1 == stacktop;    //判断栈是否为空
}


int IsFull( void )
{
    OpType *Temp;     //申明一个数据指针

    assert( NULL != Stack );   //检查输入合法性

    if( stacktop == CurrentSize - 1 )   //如果栈满
    {
        CurrentSize += INITSIZE;       //则增加栈的容量
        Temp = ( OpType * )realloc( Stack, CurrentSize * sizeof( OpType ) );   //重新分配一个栈
        if( NULL == Temp )                                                     //如果分配失败    
        {
            CurrentSize -= INITSIZE;                                           //则返回失败标志
            return 1;         //这个1代表的是返回异常情况
        }
        Stack = Temp;  //使栈顶指针重新指向新分配的空间
        return 0;      //返回
    }
    else
        return 0;     //返回
}

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-04-07 20:03
快速回复:逆波兰计算器(后缀计算器)
数据加载中...
 
   



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

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