Windows Practice_闹钟(六)_控件对象

Windows API封装思想

MFC之所以好用,那是因为MFC把Windows所有API都封装起来了,我们在使用的时候就会很方便,所以我们以后在使用Windows API的时候就需要适当的将一些Windows API封装起来,这样使用起来就会很方便了。

Win32 API创建一些列的控件

Win32 API也可以使用CreateWindow函数来创建像MFC里面的按钮(Button)、编辑框(Edit)、静态文本框(Static)等等一系列的控件窗口。
比如创建一个一个按钮窗口,使用下面的代码就可以实现:

CreateWindow(L"BUTTON", L"第一个按钮", WS_CHILD, 0, 0, 200, 100, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_FIRST), hInstance, nullptr);

创建一个静态框可以使用下面的代码:

CreateWindow(L"STATIC", L"第一个静态框", WS_CHILD, 100, 0, 200, 100, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_FIRST), hInstance, nullptr);

我们可以利用上面的例子就可以实现一个简单的计算器了。

纯Win32 API实现简单计算器

工程结构图如下:
这里写图片描述

// Calc.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include <string>
#include "Parser.h"
#include "Scanner.h"
#include "Calc.h"

#define MAX_LOADSTRING 100

#define ID_STATIC_SHOW      1001

#define ID_BUTTON_PERCENT   1002
#define ID_BUTTON_SQRT      1003
#define ID_BUTTON_SQURE     1004
#define ID_BUTTON_RECIP     1005

#define ID_BUTTON_CE        1006
#define ID_BUTTON_CLEAR     1007
#define ID_BUTTON_BACK      1008
#define ID_BUTTON_DIV       1009

#define ID_BUTTON_7         1010
#define ID_BUTTON_8         1011
#define ID_BUTTON_9         1012
#define ID_BUTTON_MULTiPLY  1013

#define ID_BUTTON_4         1014
#define ID_BUTTON_5         1015
#define ID_BUTTON_6         1016
#define ID_BUTTON_MINUS     1017

#define ID_BUTTON_1         1018
#define ID_BUTTON_2         1019
#define ID_BUTTON_3         1020
#define ID_BUTTON_PLUS      1021

#define ID_BUTTON_PLUSMINUS 1022
#define ID_BUTTON_0         1023
#define ID_BUTTON_POINT     1024
#define ID_BUTTON_EQUAL     1025


#define WIDTH   70
#define HEIGHT  40


// 全局变量: 
HINSTANCE hInst;                                // 当前实例
WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名


std::string g_strBuf;


// 此代码模块中包含的函数的前向声明: 
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: 在此放置代码。

    // 初始化全局字符串
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_CALC, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 执行应用程序初始化: 
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CALC));

    MSG msg;

    // 主消息循环: 
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  函数: MyRegisterClass()
//
//  目的: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CALC));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    //wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_CALC);
    wcex.lpszMenuName = nullptr;
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释: 
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 将实例句柄存储在全局变量中

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW & (~WS_MAXIMIZEBOX) & (~WS_MINIMIZEBOX),
      300, 300, 325, 435, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}


// HWND hStatic = CreateWindow(L"STATIC", L"", WS_CHILD, 2, 5, 305, 50, hWnd, nullptr, hInst, nullptr);
// ShowWindow(hStatic, SW_SHOW);

class CMyWindow
{
public:
    CMyWindow();
    CMyWindow(LPCTSTR   lpClassName,
        LPCTSTR   lpWindowName,
        int       x,
        int       y,
        int       nWidth,
        int       nHeight,
        HWND      hWndParent,
        HMENU     hMenu,
        HINSTANCE hInstance
    );

public:
    HWND GetHWND() const;
    void SetWindowShow(std::string str) const;

private:
    HWND m_hWnd;


};

CMyWindow::CMyWindow(): m_hWnd(nullptr)
{
}

CMyWindow::CMyWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance)
{
    m_hWnd = CreateWindow(lpClassName, lpWindowName, WS_CHILD, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, nullptr);
    ShowWindow(m_hWnd, SW_SHOW);
}

HWND CMyWindow::GetHWND() const
{
    return m_hWnd;
}

void CMyWindow::SetWindowShow(std::string str) const
{
    SetWindowTextA(m_hWnd, str.c_str());
}



class MyCalc
{
public:
    MyCalc();
    MyCalc(HWND hWnd, HINSTANCE hInstance);


    CMyWindow m_staticShow;

    CMyWindow m_buttonPercent;
    CMyWindow m_buttonSqrt;
    CMyWindow m_buttonSqure;
    CMyWindow m_buttonRecip;

    CMyWindow m_ButtonCe;
    CMyWindow m_ButtonClear;
    CMyWindow m_ButtonBack;
    CMyWindow m_ButtonDiv;

    CMyWindow m_Button7;
    CMyWindow m_Button8;
    CMyWindow m_Button9;
    CMyWindow m_ButtonMultiply;

    CMyWindow m_Button4;
    CMyWindow m_Button5;
    CMyWindow m_Button6;
    CMyWindow m_ButtonMinus;

    CMyWindow m_Button1;
    CMyWindow m_Button2;
    CMyWindow m_Button3;
    CMyWindow m_ButtonPlus;

    CMyWindow m_ButtonPlusMinus;
    CMyWindow m_Button0;
    CMyWindow m_ButtonPoint;
    CMyWindow m_ButtonEqual;
};

MyCalc::MyCalc()
{
}

MyCalc::MyCalc(HWND hWnd, HINSTANCE hInstance)
{
    m_staticShow = CMyWindow(L"STATIC", L"", 2, 25, 305, 50, hWnd, reinterpret_cast<HMENU>(ID_STATIC_SHOW), hInstance);

    m_buttonPercent = CMyWindow(L"BUTTON", L"%", 2, 100, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_PERCENT), hInstance);
    m_buttonSqrt = CMyWindow(L"BUTTON", L"√", 80, 100, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_SQRT), hInstance);
    m_buttonSqure = CMyWindow(L"BUTTON", L"x2", 158, 100, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_SQURE), hInstance);
    m_buttonRecip = CMyWindow(L"BUTTON", L"1/x", 236, 100, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_RECIP), hInstance);

    m_ButtonCe = CMyWindow(L"BUTTON", L"CE", 2, 150, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_CE), hInstance);
    m_ButtonClear = CMyWindow(L"BUTTON", L"C", 80, 150, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_CLEAR), hInstance);
    m_ButtonBack = CMyWindow(L"BUTTON", L"<-", 158, 150, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_BACK), hInstance);
    m_ButtonDiv = CMyWindow(L"BUTTON", L"÷", 236, 150, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_DIV), hInstance);

    m_Button7 = CMyWindow(L"BUTTON", L"7", 2, 200, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_7), hInstance);
    m_Button8 = CMyWindow(L"BUTTON", L"8", 80, 200, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_8), hInstance);
    m_Button8 = CMyWindow(L"BUTTON", L"9", 158, 200, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_9), hInstance);
    m_ButtonMultiply = CMyWindow(L"BUTTON", L"×", 236, 200, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_MULTiPLY), hInstance);

    m_Button4 = CMyWindow(L"BUTTON", L"4", 2, 250, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_4), hInstance);
    m_Button5 = CMyWindow(L"BUTTON", L"5", 80, 250, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_5), hInstance);
    m_Button6 = CMyWindow(L"BUTTON", L"6", 158, 250, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_6), hInstance);
    m_ButtonMinus = CMyWindow(L"BUTTON", L"-", 236, 250, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_MINUS), hInstance);

    m_Button1 = CMyWindow(L"BUTTON", L"1", 2, 300, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_1), hInstance);
    m_Button2 = CMyWindow(L"BUTTON", L"2", 80, 300, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_2), hInstance);
    m_Button3 = CMyWindow(L"BUTTON", L"3", 158, 300, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_3), hInstance);
    m_ButtonPlus = CMyWindow(L"BUTTON", L"+", 236, 300, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_PLUS), hInstance);

    m_ButtonPlusMinus = CMyWindow(L"BUTTON", L"±", 2, 350, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_PLUSMINUS), hInstance);
    m_Button0 = CMyWindow(L"BUTTON", L"0", 80, 350, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_0), hInstance);
    m_ButtonPoint = CMyWindow(L"BUTTON", L".", 158, 350, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_POINT), hInstance);
    m_ButtonEqual = CMyWindow(L"BUTTON", L"=", 236, 350, WIDTH, HEIGHT, hWnd, reinterpret_cast<HMENU>(ID_BUTTON_EQUAL), hInstance);
}


MyCalc g_calc;


//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:    处理主窗口的消息。
//
//  WM_COMMAND  - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY  - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE:
        {
        g_calc = MyCalc(hWnd, hInst);
        }
        break;
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 分析菜单选择: 
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            case ID_BUTTON_CLEAR:
                g_strBuf = "";
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_BACK:
                if (g_strBuf.size() > 0)
                {
                    g_strBuf.pop_back();
                }
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_0:
                g_strBuf += '0';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_1:
                g_strBuf += '1';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_2:
                g_strBuf += '2';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_3:
                g_strBuf += '3';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_4:
                g_strBuf += '4';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_5:
                g_strBuf += '5';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_6:
                g_strBuf += '6';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_7:
                g_strBuf += '7';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_8:
                g_strBuf += '8';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_9:
                g_strBuf += '9';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_PLUS:
                g_strBuf += "+";
                break;
            case ID_BUTTON_MINUS:
                g_strBuf += '-';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_MULTiPLY:
                g_strBuf += '*';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_DIV:
                g_strBuf += '/';
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                break;
            case ID_BUTTON_EQUAL:
                {
                char str[MAXBYTE] = { 0 };
                PoEdu::Scanner scanner(g_strBuf);
                PoEdu::Parser parser(scanner);
                sprintf_s(str, MAXBYTE, "%.f", parser.GetResult());
                g_strBuf += " = ";
                g_strBuf += str;
                g_calc.m_staticShow.SetWindowShow(g_strBuf);
                g_strBuf.clear();
                }
                break;

            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 在此处添加使用 hdc 的任何绘图代码...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

上面给出的代码只是实现了界面的功能,还有重要的一步没有实现,那就是对字符串的解析和运算。

// node.h文件
#ifndef _NODE_H_
#define _NODE_H_
#include <vector>

namespace PoEdu
{
    class NoneCopyable
    {
    protected:
        NoneCopyable();
    private:
        NoneCopyable(const NoneCopyable &otehr);
        const NoneCopyable &operator=(const NoneCopyable &other);
    };


    class Node : private NoneCopyable
    {
    public:
        virtual ~Node(void);
        virtual double Calc() const = 0;
    };


    class UnaryNode : public Node
    {
    public:
        UnaryNode(Node *node);
        ~UnaryNode();

    protected:
        Node *node_;
    };


    class BinaryNode : public Node
    {
    public:
        BinaryNode(Node *left, Node *right);
        ~BinaryNode();

    protected:
        Node *left_;
        Node *right_;
    };


    class NumberNode : public Node
    {
    public:
        NumberNode(const double number);
        double Calc() const override;

    private:
        double number_;
    };


    class MinusNode : public UnaryNode
    {
    public:
        MinusNode(Node *node);
        double Calc() const override;
    };


    class AddNode : public BinaryNode
    {
    public:
        AddNode(Node *left, Node *right);
        double Calc() const override;
    };


    class SubNode : public BinaryNode
    {
    public:
        SubNode(Node *left, Node *right);
        double Calc() const override;
    };


    class MultiPlyNode : public BinaryNode
    {
    public:
        MultiPlyNode(Node *left, Node *right);
        double Calc() const override;
    };


    class DivideNode : public BinaryNode
    {
    public:
        DivideNode(Node *left, Node *right);
        double Calc() const override;
    };


    class MultipleNode : public Node
    {
    public:
        MultipleNode(Node *node);
        ~MultipleNode();
        void AppendNode(Node *node, bool positive);

    protected:
        std::vector<Node *> nodes_;
        std::vector<bool> positives_;
    };


    class SumNode : public MultipleNode
    {
    public:
        SumNode(Node *node);
        double Calc() const override;
    };


    class ProductNode : public MultipleNode
    {
    public:
        ProductNode(Node *node);
        double Calc() const override;
    };

    class VariableNode : public Node
    {
    public:


    private:
        unsigned int id_;

    };
}

#endif// !_NODE_H_
// node.cpp文件
#include "stdafx.h"
#include <cfloat>
#include <iostream>
#include "Node.h"

namespace PoEdu
{
    NoneCopyable::NoneCopyable() {}

    NoneCopyable::NoneCopyable( const NoneCopyable &otehr ) {}

    const NoneCopyable & NoneCopyable::operator=( const NoneCopyable &other )
    {
        return *this;
    }


    Node::~Node(void) {}

    UnaryNode::UnaryNode( Node *node ) : node_(node) {}

    UnaryNode::~UnaryNode()
    {
        delete node_;
    }


    BinaryNode::BinaryNode( Node *left, Node *right ) : left_(left), right_(right) {}

    BinaryNode::~BinaryNode()
    {
        delete left_;
        delete right_;
    }


    NumberNode::NumberNode( const double number ) : number_(number) {}

    double NumberNode::Calc() const 
    {
        return number_;
    }


    MinusNode::MinusNode( Node *node ) : UnaryNode(node) {}

    double MinusNode::Calc() const 
    {
        return -node_->Calc();
    }


    AddNode::AddNode( Node *left, Node *right ) : BinaryNode(left, right) {}

    double AddNode::Calc() const 
    {
        return left_->Calc() + right_->Calc();
    }


    SubNode::SubNode( Node *left, Node *right ) : BinaryNode(left, right) {}

    double SubNode::Calc() const 
    {
        return left_->Calc() - right_->Calc();
    }


    MultiPlyNode::MultiPlyNode( Node *left, Node *right ) : BinaryNode(left, right) {}

    double MultiPlyNode::Calc() const 
    {
        return left_->Calc() * right_->Calc();
    }


    DivideNode::DivideNode( Node *left, Node *right ) : BinaryNode(left, right) {}

    double DivideNode::Calc() const 
    {
        double ret = right_->Calc();
        if (ret > DBL_EPSILON || ret < -DBL_EPSILON)
        {
            ret = left_->Calc()/ret;
        }
        else
        {
            std::cout << "除数不能为零!" << std::endl;
        }

        return ret;
    }


    MultipleNode::MultipleNode( Node * node )
    {
        AppendNode(node, true);
    }

    MultipleNode::~MultipleNode()
    {
        std::vector<Node *>::iterator it;
        for (it=nodes_.begin(); it!=nodes_.end(); ++it)
        {
            delete *it;
        }
    }

    void MultipleNode::AppendNode( Node *node, bool positive )
    {
        nodes_.push_back(node);
        positives_.push_back(positive);
    }


    SumNode::SumNode( Node *node ) : MultipleNode(node) {}

    double SumNode::Calc() const 
    {
        std::vector<Node *>::const_iterator itNode;
        std::vector<bool>::const_iterator itPositive;
        double ret = 0.0;

        for (itNode=nodes_.begin(),itPositive=positives_.begin(); itNode!=nodes_.end(); ++itNode,++itPositive)
        {
            if (*itPositive)
            {
                ret += (*itNode)->Calc();
            }
            else
            {
                ret -= (*itNode)->Calc();
            }
        }

        return ret;
    }


    ProductNode::ProductNode( Node *node ) : MultipleNode(node) {}

    double ProductNode::Calc() const 
    {
        std::vector<Node *>::const_iterator itNode;
        std::vector<bool>::const_iterator itPositive;
        double ret = 1.0, res = 0.0;

        for (itNode=nodes_.begin(),itPositive=positives_.begin(); itNode!=nodes_.end(); ++itNode,++itPositive)
        {
            if (*itPositive)
            {
                ret *= (*itNode)->Calc();
            }
            else
            {
                res = (*itNode)->Calc();
                if (res < -DBL_EPSILON || res > DBL_EPSILON)
                {
                    ret /= res;
                }
                else
                {
                    std::cout << "除数不能为零!" << std::endl;
                }
            }
        }

        return ret;
    }

}
//Parse.h文件

#ifndef _PARSER_H_
#define _PARSER_H_

namespace PoEdu
{
    class Node;
    class Scanner;

    class Parser
    {
    public:
        Parser(Scanner &scanner);
        ~Parser(void);
        double GetResult();

    private:
        Node *Expr();
        Node *Term();
        Node *Factor();

    private:
        Scanner &scanner_;
    };
}
#endif //!_PARSER_H_
// Parse.cpp文件

#include "stdafx.h"
#include <iostream>
#include "Parser.h"
#include "Node.h"
#include "Scanner.h"


namespace PoEdu
{
    Parser::Parser( Scanner &scanner ) : scanner_(scanner) {}

    Parser::~Parser(void) {}

    double Parser::GetResult()
    {
        Node *node = Expr();

        return node->Calc();
    }

    Node * Parser::Expr()
    {
        Node *ret = nullptr;
        Node *left = nullptr;
        Node *right = nullptr;

        left = Term();

        EToken token = scanner_.Token();


        if (token == TOKEN_PLUS || token == TOKEN_MINUS)
        {
            MultipleNode *multipleNode = new SumNode(left);

            do 
            {
                scanner_.Accept();
                right = Term();
                multipleNode->AppendNode(right, token == TOKEN_PLUS);
                token = scanner_.Token();
            } while (token == TOKEN_PLUS || token == TOKEN_MINUS);
            ret = multipleNode;
        }
        else
        {
            ret = left;
        }

        return ret;
    }

    Node * Parser::Term()
    {
        Node *ret = nullptr;
        Node *left = nullptr;
        Node *right = nullptr;

        left = Factor();
        EToken token = scanner_.Token();

//      switch (token)
//      {
//      case TOKEN_MULTIPLY:
//          right = Term();
//          ret = new MultiPlyNode(left, right);
//          scanner_.Accept();
//          break;
//      case TOKEN_DIVIDE:
//          right = Term();
//          ret = new DivideNode(left, right);
//          scanner_.Accept();
//          break;
//      default:
//          ret = left;
//          break;
//      }

        if (token == TOKEN_MULTIPLY || token == TOKEN_DIVIDE)
        {
            MultipleNode *multipleNode = new ProductNode(left);

            do 
            {
                token = scanner_.Token();
                scanner_.Accept();
                right = Factor();
                multipleNode->AppendNode(right, token==TOKEN_MULTIPLY);
                token = scanner_.Token();
            } while (token == TOKEN_MULTIPLY || token == TOKEN_DIVIDE);
            ret = multipleNode;
        }
        else
        {
            ret = left;
        }

        return ret;
    }

    Node * Parser::Factor()
    {
        Node *ret = nullptr;

        EToken token = scanner_.Token();

        switch (token)
        {
        case TOKEN_NUMBER:
            ret = new NumberNode(scanner_.Number());
            scanner_.Accept();
            break;
        case TOKEN_LPARENTHESES:
            ret = Expr();
            scanner_.Accept();
            if (scanner_.Token() != TOKEN_LPARENTHESES)
            {
                std::cout << "表达式错误!" << std::endl;
            }
            break;
        default:
            break;
        }

        return ret;
    }
}

// Scanner.h文件
#ifndef _SCANNER_H_
#define _SCANNER_H_
#include <string>

namespace PoEdu
{
    enum EToken
    {
        TOKEN_ERROR,
        TOKEN_END,
        TOKEN_NUMBER,
        TOKEN_PLUS,
        TOKEN_MINUS,
        TOKEN_MULTIPLY,
        TOKEN_DIVIDE,
        TOKEN_LPARENTHESES,
        TOKEN_RPARENTHESES
    };

    class Scanner
    {
    public:
        Scanner(const std::string buf);
        ~Scanner(void);
        double Number() const;
        EToken Token() const;
        std::string Symbol() const;
        void SkipWhite();
        void Accept();

    private:
        const std::string buf_;
        std::size_t curPos_;
        std::string symbol_;
        EToken token_;
        double number_;
    };
}

#endif //!_SCANNER_H_
// Scanner.cpp文件

#include "stdafx.h"
#include "Scanner.h"



namespace PoEdu
{
    Scanner::Scanner( const std::string buf ) : buf_(buf), curPos_(0), symbol_(""), token_(TOKEN_ERROR), number_(0.0)
    {
        Accept();
    }

    Scanner::~Scanner(void)
    {
    }

    double Scanner::Number() const
    {
        return number_;
    }

    PoEdu::EToken Scanner::Token() const
    {
        return token_;
    }

    std::string Scanner::Symbol() const
    {
        return symbol_;
    }

    void Scanner::SkipWhite()
    {
        while (isspace(buf_[curPos_]))
        {
            ++curPos_;
        }
    }

    void Scanner::Accept()
    {
        char *temp = nullptr;
        SkipWhite();
        switch (buf_[curPos_])
        {
        case '\0': case 'EOF': case '\r': case '\n':
            ++curPos_;
            token_ = TOKEN_END;
            break;
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
            token_ = TOKEN_NUMBER;
            number_ = strtod(&buf_[curPos_], &temp);
            curPos_ = temp - &(buf_[0]);
            break;
        case '+':
            ++curPos_;
            token_ = TOKEN_PLUS;
            break;
        case '-':
            ++curPos_;
            token_ = TOKEN_MINUS;
            break;
        case '*':
            ++curPos_;
            token_ = TOKEN_MULTIPLY;
            break;
        case '/':
            ++curPos_;
            token_ = TOKEN_DIVIDE;
            break;
        case '(':
            ++curPos_;
            token_ = TOKEN_LPARENTHESES;
            break;
        case ')':
            ++curPos_;
            token_ = TOKEN_RPARENTHESES;
            break;
        }
    }
}
// SymbolTable.h文件

#ifndef _SYMBOLTABLE_H_
#define _SYMBOLTABLE_H_
#include "stdafx.h"
#include <map>
#include <string>


namespace PoEdu
{
    class SymbolTable
    {
    public:
        SymbolTable(void);
        ~SymbolTable(void);

        unsigned int AddSymbol(const std::string &str);
        unsigned int FindSymbol(const std::string &str) const;
        std::string GetSymboName(const unsigned int id) const;
        void Clear();

    private:
        std::map<const std::string, unsigned int> dict_;
        unsigned int curId_;
    };
}
#endif //!_SYMBOLTABLE_H_
// SymbolTable.cpp文件

#include "stdafx.h"
#include "SymbolTable.h"


namespace PoEdu
{
    SymbolTable::SymbolTable(void) : curId_(0)
    {
    }

    SymbolTable::~SymbolTable(void)
    {
    }

    unsigned int SymbolTable::AddSymbol( const std::string &str )
    {
        dict_[str] = curId_;
        return curId_++;
    }

    unsigned int SymbolTable::FindSymbol( const std::string &str ) const
    {
        unsigned int ret = -1;
        std::map<const std::string, unsigned int>::const_iterator it;
        for (it=dict_.begin(); it!=dict_.end(); ++it)
        {
            if ((it->first).compare(str.c_str()) == 0)
            {
                ret = it->second;
                break;
            }
        }

        return ret;
    }

    std::string SymbolTable::GetSymboName( const unsigned int id ) const
    {
        std::string ret;
        std::map<const std::string, unsigned int>::const_iterator it;

        for (it=dict_.begin(); it!=dict_.end(); ++it)
        {
            if (it->second == id)
            {
                ret = it->first;
                break;
            }
        }

        return ret;
    }

    void SymbolTable::Clear()
    {
        dict_.clear();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值