zoukankan      html  css  js  c++  java
  • 第二部分数组和引用(基于堆栈的计算器实现)(C++ In Action 学习总结)

    1,友元

    1.1,访问控制

    当一个类声明了一个友元时,则友元可以访问该类的私有数据(has-access-to),例如,StackSeq可以访问Stack的私有数据。

    声明一个友元:friend class StackSeq

    2,引用

    2.1,定义

    引用是其它值得别名,修改引用则会更改它所引用的值,读取引用,则读取的值为所引用的值。

    2.2,创建

    引用在创建时,必须初始化,或者在声明中完成,或者在构造函数中完成,或者在调用含有引用的方法时完成。

    int a = 10;

    int &b = a; // b为a的引用

    2.3,特性

    引用传递参数,不是和值传递一样,获得参数的拷贝,而是直接引用到该值,修改引用会直接修改引用的值,也就是说,引用和所引用的值是同步的。

    常量引用可以用其它任何引用来初始化,非常量引用不能通过一个常量引用来初始化。

    3,基于堆栈的计算器的实现

    自顶向下进行设计。

    功能:对输入的数字进行压入栈中,并且每次压栈后,将显示栈中的所有元素。对输入的运算符,则取出栈栈中的两个数字,并进行操作,然后将结果压入栈中,如果此时栈中只有一个值,则将该值进行自操作,即对相同的该值进行该运算符的操作。

    Input类,定义获得输入,并且进行预处理。并将预处理结果,如果结果为数字,Number()方法则将其返回。

    Stack类,定义堆栈的操作方式

    StackSeq类,为堆栈的生成器。

    Calculator类

    bool Execute(Input const &input);方法对Input预处理后的结果,进行计算并进行栈操作。
    int Calculate(int n1, int n2, int token) const;方法,对数据进行操作
    
    
    3.1,堆栈定义和实现
    // stack.h
    /**
     * 接口文件必须包括:
     * 类的定义,
     * 指定所有的数据成员
     * 声明成员函数
     */
    
    const int maxStack = 16;
    class IStack
    {
        friend class StackSeq;  // 友元可以访问当前对象中的数据
    public:
        IStack():_top(0){}
        void Push(int i);   // 将i压入堆栈
        int Pop();     // 将堆栈顶上的元素弹出,并返回
        int Size();     // 返回栈中元素
        int Top();      // 返回栈顶元素,不返回
        bool IsFull();
        bool IsEmpty();
    
    private:
        int _arr [maxStack];
        int _top;
    };
    
    // 声明堆栈生成器
    class StackSeq
    {
    public:
        StackSeq(IStack const &stack);
        bool AtEnd() const; //是否完成
        void Advance(); //移到下一项
        int GetNum() const; //读取当前项
    private:
        IStack const & _stack; //常量引用stack,必须在构造函数前导中初始化
        int _iCur; // stack 当前引用
    };
    
    
    // stack.cpp
    #include "stack.h"
    #include <cassert>
    #include <iostream>
    
    // 通过NDEBUG=1编译去掉断言
    void IStack::Push(int i)
    {
        assert(_top < maxStack);
        _arr[_top++] = i;
    }
    
    int IStack::Pop()
    {
        assert(_top > 0);
        return _arr[--_top];
    }
    
    int IStack::Size()
    {
        return _top;
    }
    
    int IStack::Top()
    {
        assert(_top != 0);
        return _arr[_top - 1];
    }
    
    bool IStack::IsFull()
    {
        return _top == maxStack;
    }
    
    bool IStack::IsEmpty()
    {
        return _top == 0;
    }
    
    // 堆栈序列生成器定义
    StackSeq::StackSeq(const IStack &stack) : _iCur(0), _stack(stack)
    {}
    
    bool StackSeq::AtEnd() const
    {
        return _iCur == _stack._top;
    }
    
    void StackSeq::Advance()
    {
        assert(!AtEnd());   // 非结尾
        ++_iCur;
    }
    int StackSeq::GetNum() const
    {
        assert(!AtEnd());
        return _stack._arr[_iCur];
    }
    
    
    3.2,输入/输出操作
    // input.h
    //
    // Created by FLanWu on 2020/11/13.
    //
    
    // 条件编译指令,防止重复定义
    # if !defined input_h
    #define input_h
    const int maxBuf = 100;
    
    const int tokNumber = 1;
    const int tokError = 2;
    
    // 获取输入并进行预处理
    class Input
    {
    public:
        Input();
        int Token() const
        {
            return _token;
        }
        int Number() const;
    
    private:
        int _token;
        char _buf[maxBuf];
    };
    
    
    #endif
    
    
    // input.cpp
    #include <iostream>
    #include <cctype>   // 包含识别字符类型,isdigit宏,可以判断字符是否为数字
    #include <cstdlib>  // 包含atoi()将ascii转换为整数
    #include <cassert>
    #include "input.h"
    
    Input::Input()
    {
        std::cin >> _buf;
    
        // 判断输入的第一个字符是什么
        int c = _buf[0];
        if (std::isdigit(c))	
        {
            _token = tokNumber;
        } else if (c == '+' || c == '*' || c == '/')
        {
            _token = c;
        } else if (c == '-') //允许输入负数
        {
            if (std::isdigit(_buf[1]))  // 参照下一个字符
            {
                _token = tokNumber;
            } else
            {
                _token = c;
            }
        } else
        {
            _token = tokError;
        }
    }
    
    int Input::Number() const   // 将缓冲器中的字符转换为字符串
    {
        assert(_token == tokNumber);
        return std::atoi(_buf); //将字符串转换为整数
    }
    
    3.2,Calculator的定义和实现
    // calc.h
    //
    // Created by FLanWu on 2020/11/13.
    //
    #include "input.h"
    #include "stack.h"
    
    class Calculator
    {
    public:
        bool Execute(Input const &input);
        // 让stack可以访问
        IStack const & GetStack() const
        {
            return _stack;
        }
    
    private:
        int Calculate(int n1, int n2, int token) const;
        IStack _stack;
    
    };
    
    // calc.cpp
    //
    // Created by FLanWu on 2020/11/13.
    //
    #include <iostream>
    #include <cassert>
    #include "calc.h"
    #include "stack"
    #include "input.h"
    
    bool Calculator::Execute(const Input &input)
    {
        // 对堆栈进行提出数字并将计算结果重新压入堆栈。
        int token = input.Token();
        bool status = false; // 状态初始为失败
        if (token == tokError)
        {
            std::cout << "Unknown token
    ";
        } else if (token == tokNumber)
        {
            if (_stack.IsFull())
            {
                std::cout << 'Stack is full
    ';
            } else
            {
                _stack.Push(input.Number());
                status = true;
            }
        } else
        {
            // 约定: Input不能产生任何其它符号
            assert(token == '+' || token == '-' || token == '*' || token == '/');
            if (_stack.IsEmpty())
            {
                std::cout << "Stack is empty
    ";
            } else
            {
                int num2 = _stack.Pop();
                int num1;
                if (_stack.IsEmpty())
                {
                    num1 = num2;
                } else
                {
                    num1 = _stack.Pop();
                }
                _stack.Push(Calculate(num1,num2,token));
                status = true;
            }
        }
        return status;
    }
    
    int Calculator::Calculate(int n1, int n2, int token) const
    {
        int result;
        if(token == '+')
            result = n1 + n2;
        else if(token == '-')
            result = n1 - n2;
        else if(token == '*')
            result = n1 * n2;
        else if(token == '/')
        {
            if(n2 == 0)
            {
                std::cout << "Division by zero
    ";
                result = 0;
            } else
                result = n1 / n2;
        }
        return result;
    }
    
    3.3,main函数测试
    #include <iostream>
    #include "calc.h"
    
    using namespace std;
    
    int main()
    {
        Calculator TheCalculator;
        bool status;
        do
        {
            std::cout <<">>>";
            Input input;
            status = TheCalculator.Execute(input);
            if(status)
            {
                for(StackSeq seq(TheCalculator.GetStack()); !seq.AtEnd(); seq.Advance())
                {
                    std::cout << " " << seq.GetNum() << std::endl;
                }
    
            }
        }while (status);
        return 0;
    }
    
    

    输出结果:

    >>>1
     1
    >>>2
     1
     2
    >>>3
     1
     2
     3
    >>>-1
     1
     2
     3
     -1
    >>>+
     1
     2
     2
    >>>+
     1
     4
    >>>-
     -3
    >>>+
     -6
    >>>sjad
    Unknown token
    
  • 相关阅读:
    硬件加速器为人工智能应用服务
    js 获取指定字符串个数
    js 仿微信投诉—引入vue.js,拆分组件为单个js
    css 图片波浪效果
    svg path命令
    谷歌浏览器—打断点调试页面
    js 实现加载百分比效果
    js 实现纵向轮播
    css 图片高度自适应
    js 禁止/允许页面滚动
  • 原文地址:https://www.cnblogs.com/jlxa162hhf/p/14161221.html
Copyright © 2011-2022 走看看