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();
}
}