编程实现计算器

需求

编程实现计算器,当输入一个表达式时,可以得出计算结果。(实现加、减、乘、除、取余以及负号运算)

思路

1. 维护两个栈,一个栈my_dig用于push数字,另一个栈my_op用于push运算符。栈中元素结构如下:

typedef struct tag_stack1
{
    int dig_arr[1024];
    int dig_top;
}DIG, *pDIG;

typedef struct tag_stack2
{
    char op_arr[1024];
    int  op_top;
}OP, *pOP;

2. 遍历表达式字符串,当遇到数字时,将数字push到栈my_dig中,这个没有问题。对于运算符需要讨论:

1)如果运算符是右括号,则my_op需要一直弹栈计算,直到左括号出栈。

2)如果运算符不是右括号,则需判断当前运算符与栈顶运算符的优先级高低,如果当前运算符优先级高,则入栈;否则弹栈计算,直到当前运算符优先级低于栈顶运算符优先级为止,此时当前运算符入栈。

注意

需要区分负号与其他运算符。本代码处理负号的入栈时,将其替换成‘@’,以便区分其与减号。

1. 减号与负号,两者优先级不同。

2. 对于负号的计算,每次从数字栈中只取一个操作数,而对于其他运算符(包括减号)的计算,每次从数字栈中需要取两个操作数。

代码

/*************************************************************************
  > File Name: main.c
  > Author: KrisChou
  > Mail:[email protected]
  > Created Time: Wed 10 Sep 2014 07:44:10 PM CST
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct tag_stack1
{
    int dig_arr[1024];
    int dig_top;
}DIG, *pDIG;

typedef struct tag_stack2
{
    char op_arr[1024];
    int  op_top;
}OP, *pOP;

static int is_ok[8][8] =
{
    //      + - * / % ( # @ )
    /* + */ 0,0,0,0,0,1,1,0,
    /* - */ 0,0,0,0,0,1,1,0,
    /* * */ 1,1,0,0,0,1,1,0,
    /* / */ 1,1,0,0,0,1,1,0,
    /* % */ 1,1,0,0,0,1,1,0,
    /* ( */ 1,1,1,1,1,1,1,1,
    /* # */ 0,0,0,0,0,0,0,0,
    /* @ */ 1,1,1,1,1,1,1,0
};

static char op_arr[9] = {‘+‘,‘-‘,‘*‘,‘/‘,‘%‘,‘(‘,‘#‘,‘@‘,‘)‘};

static int find_index(char op)
{
    int index;
    for(index = 0; index < 9; index++)
    {
        if(op == op_arr[index])
        {
            return index;
        }
    }
    return -1;
}

static int is_myspace(char c)
{
    if(c == ‘ ‘ || c == ‘\n‘ || c == ‘\t‘ || c == ‘\v‘)
    {
        return 1;
    }else
    {
        return 0;
    }
}

static void trim_space(char *str)
{
    int slow = -1;
    int fast = 0;
    while(str[fast] != ‘\0‘)
    {
        if(!is_myspace(str[fast]))
        {
            str[++slow] = str[fast];
        }
        fast++;
    }
    str[++slow] = ‘\0‘;
}

static int calculate(char op, int left, int right)
{
    switch(op)
    {
        case(‘+‘):return left + right;break;
        case(‘-‘):return left - right;break;
        case(‘*‘):return left * right;break;
        case(‘/‘):return left / right;break;
        case(‘%‘):return left % right;break;
    }
}

int handler(char *str)
{
    OP my_op;
    DIG my_dig;
    memset(&my_op,0,sizeof(OP));
    memset(&my_dig,0,sizeof(DIG));      //两个栈,栈顶元素均指向下一个要入栈的位置
    my_op.op_arr[my_op.op_top++] = ‘#‘;
    int result = 0;
    int index  = 0;
    for( index = 0; str[index] != ‘\0‘; index++ )
    {
        int numb;
        if( find_index(str[index]) >= 0 && find_index(str[index] <= 8)) /* 操作符 */
        {
            int left,right;
            char stk_op;
            int tmp_result;
            if(str[index] == ‘)‘)
            {
                while(my_op.op_arr[my_op.op_top-1] != ‘(‘)
                {
                    stk_op = my_op.op_arr[--my_op.op_top];
                    right  = my_dig.dig_arr[--my_dig.dig_top];
                    if(stk_op == ‘@‘)
                    {
                        tmp_result = -right;
                    }else
                    {
                        left   = my_dig.dig_arr[--my_dig.dig_top];
                        tmp_result = calculate(stk_op, left, right);
                    }
                    my_dig.dig_arr[my_dig.dig_top++] = tmp_result;  //新操作数入栈
                }
                my_op.op_top--;//‘(‘也出栈
            }else
            {

                if(      //操作符为负号
                        str[index] == ‘-‘ &&
                        ( (index > 0 && find_index(str[index-1])>=0 && find_index(str[index-1])<=4) ||
                          (index > 0 && str[index-1] == ‘(‘)                                        ||
                          (index > 0 && str[index-1] == ‘@‘)                                        ||
                          (index == 0 )
                        )
                  )
                {
                    str[index] = ‘@‘;
                }

                while(1)
                {
                    stk_op = my_op.op_arr[my_op.op_top-1];
                    if( is_ok[find_index(str[index])][find_index(stk_op)] ) //运算符可以进栈
                    {
                        my_op.op_arr[my_op.op_top++] = str[index];
                        break;
                    }else
                    {
                        my_op.op_top--;
                        right  = my_dig.dig_arr[--my_dig.dig_top];
                        if(stk_op == ‘@‘)
                        {
                            tmp_result = -right;
                        }else
                        {
                            left   = my_dig.dig_arr[--my_dig.dig_top];
                            tmp_result = calculate(stk_op, left, right);
                        }
                        my_dig.dig_arr[my_dig.dig_top++] = tmp_result;  //新操作数入栈
                    }
                }
            }

        }else                             /* 操作数 */
        {
            numb = 0;
            while(str[index] >= ‘0‘ && str[index] <= ‘9‘)
            {
                numb = numb * 10 + str[index] - ‘0‘;
                index++;
            }
            my_dig.dig_arr[my_dig.dig_top++] = numb;
            index--;
        }
    }

    while(my_op.op_arr[my_op.op_top-1] != ‘#‘)
    {
        int stk_op = my_op.op_arr[--my_op.op_top];
        int right  = my_dig.dig_arr[--my_dig.dig_top];
        int tmp_result;
        int left;
        if(stk_op == ‘@‘)
        {
            tmp_result = -right;
        }else
        {
            left   = my_dig.dig_arr[--my_dig.dig_top];
            tmp_result = calculate(stk_op, left, right);
        }
        my_dig.dig_arr[my_dig.dig_top++] = tmp_result;  //新操作数入栈
    }
    result = my_dig.dig_arr[--my_dig.dig_top];
    return result;
}

int main(int argc, char *argv[])
{
    int ret;
    char str[1024];
    while(fflush(stdin),memset(str,0,1024),fgets(str,1024,stdin))
    {
        trim_space(str);
        ret = handler(str);
        printf("the result is %d\n", ret);
    }
    return 0;
}
 
时间: 2024-10-28 15:45:25

编程实现计算器的相关文章

菜鸟学Android编程——简单计算器《一》

菜鸟瞎搞,高手莫进 本人菜鸟一枚,最近在学Android编程,网上看了一些视频教程,于是想着平时手机上的计算器应该很简单,自己何不尝试着做一个呢? 于是就冒冒失失的开撸了. 简单计算器嘛,功能当然很少,加减乘除就可以. 第一步:设计布局文件 界面如下图: 由于刚开始学Android,对布局文件也不是很了解,边查边找,最后凑合着写好了布局文件. 注意事项:此布局文件用到了GridLayout布局,是在Android4.0以上才出现的(不知道谷歌有没有开发相应的包来适配4.0以下版本). 有关Gri

C#编程普通型计算器 经验与感悟

先贴图: 这是用C# 语言编写的普通型计算器,功能基本模仿Windows8自带计算器程序(版本6.3,内部版本9600).支持加.减.乘.除.退格.清除.平方根.倒数.相反数.连续四则.连续等号.自动补齐.记忆.键盘输入等功能.可以应对已知的多种形式输入而不发生崩溃,计算结果基本正确. 但是该计算器与Windows自带版本相比还有很多不足:例如,精度无法达到后者水平:“显示屏”部分只有一行,无法显示当前运算式子:未对运算时十进制与二进制相互转化数据丢失现象做优化(例如 12.45 – 12.4

Python: UI编程之计算器

起源: 研究Python UI编程,我偏喜欢其原生组件,于是学习Tkinter.ttk组件用法.找一计算器开源代码,略加修整,以为备忘.其界面如图所示: 1.源代码(Python 2.7): # encoding: UTF-8 from Tkinter import * from ttk import * calc = Tk() calc.title('计算器') calc.resizable(False, False) buttons = [ '7', '8', '9', '*', 'C',

spring相关—AOP编程—数学计算器情景示例讲解(包含注解配置AOP与XML配置AOP)

1.数学计算器 ①数学计算器接口[MathCalculator]            public void add(int i,int j);     public int sub(int i,int j);     public int multi(int i,int j);     public void divide(int i,int j);    ②提供简单实现:加减乘除运算[EasyImpl]    ③在简单实现的基础上让每一个计算方法都能够打印日志[LoginImpl]    

python 编程之计算器

作业: 使用正则表达式和递归实现计算器功能. 实现: 1.实现带括号的计算 2.实现指数.加减乘除求余等功能 一.实例说明: 本实例自己写了个版本,但依旧存在一点bug,例:-2-2等计算问题,故最后在武SIR的代码基础上加了指数.求余等功能. 该计算器思路:1.递归寻找表达式中只含有 数字和运算符的表达式,并计算结果2.由于整数计算会忽略小数,所有的数字都认为是浮点型操作,以此来保留小数使用技术:1.正则表达式2.递归 二.流程图: 三.代码: #!/usr/bin/python27 #_*_

java图形界面编程及计算器

import java.awt.*;import java.awt.event.*;import java.util.Date;import javax.swing.*;public class 个人信息{ public static void main(String arg[]) { Frame f=new Frame("个人信息"); f.setSize(250,300); f.setLocation(300,300); f.setBackground(Color.lightGra

shell编程写计算器加减乘除(暨慕课Tony老师作业)

简单计算器的编程【C++】

第一篇博客嘎嘎 这篇是用栈去编程简单计算器 关键词:atoi().memset()[https://blog.csdn.net/qq_27522735/article/details/53374765].printf("%.2f\n", x)[保留两位小数] #include <iostream> #include <cstdio> #include <vector> #include <stack> #include <cstri

java-第十三章-类的无参方法(一)-代参方法的编程计算器

package 本章总结; public class A01class { public int ope(int Operator, int num1, int num2) { switch (Operator) { case 1: num1 += num2; break; case 2: num1 -= num2; break; case 3: num1 *= num2; break; case 4: num1 /= num2; break; default: System.out.print