| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3406 人关注过本帖
标题:中缀计算器
只看楼主 加入收藏
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
结帖率:95.65%
收藏
已结贴  问题点数:100 回复次数:7 
中缀计算器
基本运算已经完成,可以进行 + - × /  幂 以及负数计算, 可以正确判断圆括号的优先级,以及表达式的合法性。


程序代码:
#include <stdio.h>
#include "Stack.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include <math.h>


typedef char OperatorType;
typedef double OpType;
int
getoperand( void );
void
Introduce( void );
void
Help( void );
void
Precision( int *precision );
void
Plus( OperatorType ch );
void
Product( OperatorType ch );
void
Power( OperatorType ch );
void
LeftParenthes( OperatorType ch );
void
RightParenthes( void );
void
Factorial( OperatorType ch );
void
Compute( OperatorType ch );
void
End( int precision );
void
ErrorProcess( void );
jmp_buf restart;


int
main( void )
{
    int ch;
    int precision;

    precision = 2;

    Introduce();
    setjmp( restart );
    while( EOF != ( ch = getoperand() ) )
    {
        switch( ch )
        {
            case '+':
            case '-':
                Plus( ch );
                break;
            case '*':
            case '/':
            case '%':
                Product( ch );
                break;
            case '^':
                Power( ch );
                break;
            case '!':
                Factorial( ch );
                break;
            case '(':
                LeftParenthes( ch );
                break;
            case ')':
                RightParenthes();
                break;
            case '\n':
                End( precision );
                break;
            case 'H':
            case 'h':
                Help();
                getchar();
                break;
            case 'j':
            case 'J':
                Precision( &precision );
                break;
            case ' ':
                break;
            default:
                ErrorProcess();
                break;
        }
    }
    return 0;
}


void
Introduce( void )
{
    printf( "这是一个提供加、减、乘、除、阶乘、幂、模运算的计算器。\n"
            "输入的任一表达式以回车结束。\n"
        "如果表达式最后的运算符为右(圆、方、花)括号,则该括号可以省略。\n"
             "输入h查看帮助。\n");
}


void
Help( void )
{
    printf( "加运算符:+\n"
        "减运算符:-\n"
        "乘运算符:*\n"
        "除运算符:/(除数不可以为0)\n"
        "幂运算符:^(Shift + 6)(例如:3^2 或 3^2.5)\n"
        "阶乘运算符:!(Shift + 1)(例如:3!)\n"
        "模运算符:%%(Shift + 5)(例如:3%%2)\n"
             "调节精度: j\n" );
    printf( "\n注意:\n      阶乘很容易造成溢出,请小心使用这个运算符!\n"
        "      阶乘溢出所得的值将为0。\n"
        "      阶乘运算符的操作数必须是整数!\n\n" );
}


MAKE_STACK( OperatorType, _Operator, 128 )
MAKE_STACK( OpType, _Op, 128 )//操作数简写为Op
#define MAXSIZE 128


int
getoperand( void )
{
    char Src[ MAXSIZE ];
    int ix, ch;

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

    if( '{' == ch || '[' == ch )
        ch = '(';
    else if( '}' == ch || ']' == ch )
        ch = ')';

    Src[ ix ] = '\0';
    if( 1 == ix && '-' == Src[ 0 ] )
        return Src[ 0 ];
    if( 0 < ix )
        Posh_Op( atof( Src ) );

    return ch;
}


void
End( int precision )
{
    OperatorType t;
    OpType temp;

    if( Is_Empty_Op() && Is_Empty_Operator() )
        return;

    while( !Is_Empty_Operator() )
    {
        if( '(' != ( t = Top_Operator() ) )
            Compute( t );
        Pop_Operator();
    }

    temp = Top_Op();
    Pop_Op();
    if( Is_Empty_Op() )
        printf("%.*lf\n\n", precision, temp );
    else
        printf( "\n错误的表达式,数据已清空,请重新输入。\n" );
    DeleteStack_Op();
}


void
Precision( int *precision )
{
    while( printf( "输入新的精度( 0 - 20 ):" ) )
    {
        scanf( "%d", precision );
        getchar();
        if( 0 <= *precision && 20 >= *precision )
        {
            printf( "精度设置为:%d\n", *precision );
            break;
        }
        else
            printf( "精度范围错误,重新输入(精度范围为0 - 20)\n" );
    }
}


void
Plus( OperatorType ch )
{
    OperatorType t;

    if( Is_Empty_Op() )
        ErrorProcess();
    if( !Is_Empty_Operator() && '(' != ( t = Top_Operator() ) )
    {
        Compute( t );
        Pop_Operator();
    }
    Posh_Operator( ch );
}


void
Product( OperatorType ch )
{
    OperatorType t;

    if( Is_Empty_Op() )
        ErrorProcess();
    if( !Is_Empty_Operator() )
        if( '*' == ( t = Top_Operator() ) || '/' == t || '^' == t || '%' == t )
        {
            Pop_Operator();
            Compute( t );
        }

    Posh_Operator( ch );
}


void
Power( OperatorType ch )
{
    OperatorType t;

    if( Is_Empty_Op() )
        ErrorProcess();
    if( !Is_Empty_Operator() && '^' == ( t = Top_Operator() ) )
    {
        Pop_Operator();
        Compute( t );
    }

    Posh_Operator( ch );
}


void
Factorial( OperatorType ch )
{
    Compute( ch );
}


void
LeftParenthes( OperatorType ch )
{
    Posh_Operator( ch );
}


void
RightParenthes( void )
{
    OperatorType t;

    while( !Is_Empty_Operator() && '(' != ( t = Top_Operator() ) )
    {
        Pop_Operator();
        Compute( t );
    }
    Pop_Operator();
}


void
Compute( OperatorType ch )
{
    OpType op1, op2;
    int i;
    int product;
    static int Lilisi = 0;

    if( !Is_Empty_Op() )
    {
        op1 = Top_Op();
        Pop_Op();
    }
    else
        ErrorProcess();

    if( !Is_Empty_Op() && '!' != ch )
    {
        op2 = Top_Op();
        Pop_Op();
    }
    else if( Is_Empty_Op() && '!' != ch )
        ErrorProcess();

    switch( ch )
    {
        case '+':
            Posh_Op( op1 + op2 );
            break;
        case '-':
            Posh_Op( op2 - op1 );
            break;
        case '*':
            Posh_Op( op1 * op2 );
            break;
        case '/':
            if( 0 == op1 )
            {
                if( 0 == Lilisi++ )
                {
                    printf( "\n假设你有0块饼干,要将它分给0个朋友,每个朋友能分到几块饼干?\n" 
                        "你看,这个问题没有半毛钱意义。\n"
                        "你的朋友会很难过,因为没有饼干吃.\n"
                        "你也会很难过,因为你一个朋友也没有。\n");
                }
                printf( "\n除数不能为0!\n" );
                ErrorProcess();
            }
            Posh_Op( op2 / op1 );
            break;
        case '%':
            if( 0 == op1 )
                ErrorProcess();
             Posh_Op( fmod( op2, op1 ) );
             break;
        case '^':
            Posh_Op( pow( op2, op1 ) );
            break;
        case '!':
            if( 0 > op1 )
                ErrorProcess();
            for( i = 1, product = 1; i <= ( int )op1; ++i )
                product *= i;
            Posh_Op( product );
            break;
        default:
            break;
    }
}


void
ErrorProcess( void )
{
    DeleteStack_Op();
    DeleteStack_Operator();
    while( '\n' != getchar() )
        ;
    printf("\n错误的表达式,数据已清空,重新输入!\n");
    longjmp( restart, 1 );
}



程序代码:
/* Stack.h */
#define MAKE_STACK( Stack_type, Suffix, size )            \
    static Stack_type Stack##Suffix[ size ];        \
    static int TopLx##Suffix = -1;                \
                                \
    int                            \
    Is_Empty##Suffix( void )                 \
    {                            \
        return -1 == TopLx##Suffix;            \
    }                            \
                                \
    int                            \
    Is_Full##Suffix( void )                    \
    {                            \
        return size - 1 == TopLx##Suffix;        \
    }                            \
                                \
                                \
    void                            \
    Posh##Suffix( Stack_type value )            \
    {                            \
        Stack##Suffix[ ++TopLx##Suffix ] = value;    \
    }                            \
                                \
    void                            \
    Pop##Suffix( void )                    \
    {                            \
        --TopLx##Suffix;                \
    }                            \
                                \
    Stack_type                        \
    Top##Suffix( void )                    \
    {                            \
        return Stack##Suffix[ TopLx##Suffix ];        \
    }                            \
                                \
    void                            \
    DeleteStack##Suffix( void )                \
    {                            \
        TopLx##Suffix = -1;                \
    }
       


[此贴子已经被作者于2017-5-29 19:26编辑过]

搜索更多相关主题的帖子: 计算器 color 
2017-04-08 13:54
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:100 
推荐几个网址参考~

https://bbs.bccn.net/thread-379969-1-1.html

https://bbs.bccn.net/thread-462594-1-1.html

https://bbs.bccn.net/thread-403018-1-1.html

其实不久前我自己用自己的方法曾经做了一个~不过代码太长而且写得很不系统就不贴出来了~~~~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-04-08 16:04
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-08 16:08
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
基本操作终于完成啦,考虑加上幂运算 取模运算会不会更好了。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-09 16:20
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
我发现我这个计算器完善度还是挺高的。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-29 17:34
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 5楼 renkejun1942
我就对饼干感兴趣~见一次笑一次~~
这个我最近也开始消化了~~感觉虽然Emotiona那个输入不当会点bug~不过有注解看容易消化很多~~你这个看上去好像没有刻意去设置运算符优先级~就是对不同优先级的用不同的函数处理~这个我要消化一下才行~~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-05-29 19:48
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 6楼 九转星河
你不会刻意去触发饼干吧?
不过……我自己经常去触发。

运算符的优先级是通过对比前一个运算符来判断的,比如,第一个运算符是加号,那么直接入栈,第二个运算符也是加号,那么前面的那个加号就可以使用,如果第二个运算符是乘号,那么操作数不够,我们需要再获得一个操作数,因此我们要到第三个运算符,再来判断前者的乘号是否可以被使用。

我历来不写注释的,就算写到发出来我也会删掉的。

[此贴子已经被作者于2017-5-29 22:00编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-29 20:18
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 7楼 renkejun1942
不写注释给人一种大手的味道~我写注释是为了便于理解~不过如果我自己能理解有时也不会去写注释~就是这样~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-05-29 22:28
快速回复:中缀计算器
数据加载中...
 
   



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

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