赞
踩
算是纪念自己头一次开始结合自己所学写简单的“小项目”,实际上还是很“菜”的。
开始时无论是对于编程语言本身的掌握(目前学习到的C++和Java),还是有一个大概的框架规划,我都感觉自己无从下手,因此也去“临时抱佛脚”再学了一些,CSDN 也好,B站也罢,总之确实学到的不少,因此记录下来,算是见证自己的进步吧!
一、MFC的基本介绍
百度百科的解释:MFC全称为Microsoft Foundation Classes ,是微软公司提供的一个类库,以C++的形式封装了Windows API,并且包含一个应用程序框架,便于应用程序开发人员使用!
为了实现用C++编写实现可视化的简单计算器,我选择Visual Studio 2019版本中的MFC来开发这个小项目,此外还参考了B站的MFC基本操作的视频,用以更好的帮助自己完成项目!
二、算术表达式
1、算术表达式的特点:
(1)操作数之间的相对次序不变;
(2)运算符的相对次序不同;
(3)后缀表达式中已考虑了运算符的优先级,没有括号,只有操作数和运算符。
列:算术表达式求值 :参与运算的数据(即操作数)可以为整数或实数,运算符(即操作符)为+、-、、/(加、减、乘、除)等二元操作符,包括圆括号;
如 :
56+10-25=15或者 6+(5-4/2)*3=15
运算规则:先乘除,后加减,从左到右计算,先括号内,后括号外;
2、中缀表达式转换为后缀表达式
(1)存储结构
①后缀表达式队列:postQueue,用于存储逆波兰表达式(其实不用队列排序直接输出也行)
②操作符栈:opStack,对用户输入的操作符进行处理,用于存储运算符
(2)算法思想
从左向右依次读取算术表达式的元素X,分以下情况进行不同的处理:
1)如果X是操作数,直接入队
2)如果X是运算符,再分以下情况:
a)如果栈为空,直接入栈。
b)如果X==”(“,直接入栈。
c)如果X==”)“,则将栈里的元素逐个出栈,并入队到后缀表达式队列中,直到第一个配对的”(”出栈。(注:“(”和“)”都不 入队)
d)如果是其他操作符(+ - * /),则和栈顶元素进行比较优先级。 如果栈顶元素的优先级大于等于X,则出栈并把栈中弹出的元素入队,直到栈顶元素的优先级小于X或者栈为空。弹出完这些元素后,才将遇到的操作符压入到栈中。
3)最后将栈中剩余的操作符全部入队。
3、后缀表达式的计算
(1)需要用到一个结果栈Res_Stack :用于存放计算的中间过程的值和最终结果
(2)算法思想
首先准备一个栈Res_Stack.
1)从左开始向右遍历后缀表达式的元素。
2)如果取到的元素是操作数,直接入栈Res_Stack,如果是运算符,从栈中弹出2个数进行运算,然后把运算结果入栈
3) 当遍历完后缀表达式时,计算结果就保存在栈里了。
1、首先是创建一个MFC项目用来显示基本的窗口
2、之后创建相应的“.h” 头文件
3、接着创建“.cpp”源文件用于实现计算器功能及可视化
1、首先是如何通过MFC显示一个窗口
2、“.h”文件的创建
// xch-CakulatorDlg.h: 头文件
//
#pragma once
//运算符
enum Calcuator_Flag
{
FLAG_ADD,
FLAG_SUB,
FLAG_MUL,
FLAG_DIV,
};
// CxchCakulatorDlg 对话框
class CxchCakulatorDlg : public CDialogEx
{
// 构造
public:
CxchCakulatorDlg(CWnd* pParent = nullptr); // 标准构造函数
void SaveFirstValue(); //保存第一个输入值
void Calculator(); //计算
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_XCHCAKULATOR_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() private: CString str; //编辑框1内的字符 CString str1; //编辑框2内的字符 CString str2; CString str3; CString str4; CString str5; CString str6; CString TempStr; double NUM1; //输入两个数 double NUM2; Calcuator_Flag Flag; public: afx_msg void OnBnClickedButtonnum0(); afx_msg void OnBnClickedButtonnum1(); afx_msg void OnBnClickedButtonnum2(); afx_msg void OnBnClickedButtonnum3(); afx_msg void OnBnClickedButtonnum4(); afx_msg void OnBnClickedButtonnum5(); afx_msg void OnBnClickedButtonnum6(); afx_msg void OnBnClickedButtonnum7(); afx_msg void OnBnClickedButtonnum8(); afx_msg void OnBnClickedButtonnum9(); afx_msg void OnBnClickedButtonback(); afx_msg void OnBnClickedButtonclear(); afx_msg void OnBnClickedButtonpoint(); afx_msg void OnBnClickedButtonadd(); afx_msg void OnBnClickedButtonsub(); afx_msg void OnBnClickedButtonmul(); afx_msg void OnBnClickedButtondiv(); afx_msg void OnBnClickedButtonequal(); afx_msg void OnBnClickedClearall(); };
3、“.c”文件的创建
// // // xch-CakulatorDlg.cpp: 实现文件 // #include "pch.h" #include "framework.h" #include "xch-Cakulator.h" #include "xch-CakulatorDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx { public: CAboutDlg(); // 对话框数据 #ifdef AFX_DESIGN_TIME enum { IDD = IDD_ABOUTBOX }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CxchCakulatorDlg 对话框 CxchCakulatorDlg::CxchCakulatorDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_XCHCAKULATOR_DIALOG, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CxchCakulatorDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT1, str); DDX_Text(pDX, IDC_EDIT2, str1); DDX_Text(pDX, IDC_EDIT3, str2); DDX_Text(pDX, IDC_EDIT4, str3); DDX_Text(pDX, IDC_EDIT5, str4); DDX_Text(pDX, IDC_EDIT6, str5); DDX_Text(pDX, IDC_EDIT7, str6); } BEGIN_MESSAGE_MAP(CxchCakulatorDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTONNum0, &CxchCakulatorDlg::OnBnClickedButtonnum0) ON_BN_CLICKED(IDC_BUTTONNum1, &CxchCakulatorDlg::OnBnClickedButtonnum1) ON_BN_CLICKED(IDC_BUTTONNum2, &CxchCakulatorDlg::OnBnClickedButtonnum2) ON_BN_CLICKED(IDC_BUTTONNum3, &CxchCakulatorDlg::OnBnClickedButtonnum3) ON_BN_CLICKED(IDC_BUTTONNum4, &CxchCakulatorDlg::OnBnClickedButtonnum4) ON_BN_CLICKED(IDC_BUTTONNum5, &CxchCakulatorDlg::OnBnClickedButtonnum5) ON_BN_CLICKED(IDC_BUTTONNum6, &CxchCakulatorDlg::OnBnClickedButtonnum6) ON_BN_CLICKED(IDC_BUTTONNum7, &CxchCakulatorDlg::OnBnClickedButtonnum7) ON_BN_CLICKED(IDC_BUTTONNum8, &CxchCakulatorDlg::OnBnClickedButtonnum8) ON_BN_CLICKED(IDC_BUTTONNum9, &CxchCakulatorDlg::OnBnClickedButtonnum9) ON_BN_CLICKED(IDC_BUTTONBack, &CxchCakulatorDlg::OnBnClickedButtonback) ON_BN_CLICKED(IDC_BUTTONClear, &CxchCakulatorDlg::OnBnClickedButtonclear) ON_BN_CLICKED(IDC_BUTTONPoint, &CxchCakulatorDlg::OnBnClickedButtonpoint) ON_BN_CLICKED(IDC_BUTTONAdd, &CxchCakulatorDlg::OnBnClickedButtonadd) ON_BN_CLICKED(IDC_BUTTONSub, &CxchCakulatorDlg::OnBnClickedButtonsub) ON_BN_CLICKED(IDC_BUTTONMul, &CxchCakulatorDlg::OnBnClickedButtonmul) ON_BN_CLICKED(IDC_BUTTONDiv, &CxchCakulatorDlg::OnBnClickedButtondiv) ON_BN_CLICKED(IDC_BUTTONEqual, &CxchCakulatorDlg::OnBnClickedButtonequal) ON_BN_CLICKED(ClearAll, &CxchCakulatorDlg::OnBnClickedClearall) END_MESSAGE_MAP() // CxchCakulatorDlg 消息处理程序 BOOL CxchCakulatorDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != nullptr) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CxchCakulatorDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CxchCakulatorDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CxchCakulatorDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CxchCakulatorDlg::SaveFirstValue() { UpdateData(TRUE); NUM1 = _wtof(str); TempStr = str; str = L""; UpdateData(FALSE); } void CxchCakulatorDlg::Calculator() { UpdateData(TRUE); NUM2 = _wtof(str); double result = 0.0f; switch (Flag) { case FLAG_ADD: result = NUM1 + NUM2; TempStr = TempStr + _T("+") + str + _T("="); break; case FLAG_SUB: result = NUM1 - NUM2; TempStr = TempStr + _T("-") + str + _T("="); break; case FLAG_MUL: result = NUM1 * NUM2; TempStr = TempStr + _T("*") + str + _T("="); break; case FLAG_DIV: if (NUM2 == 0.0f) { result = NUM1; TempStr = _T("--除数不能为0!!!--"); } else { result = NUM1 / NUM2; TempStr = TempStr + _T("/") + str + _T("="); break; } default: break; } //如果浮点数是个整数,就显示为整数 if (result - int(result) <= 1e-5) { str.Format(L"%d", (int)result); } else { str.Format(L"%f", result); } TempStr += str; str5 = str4; str4 = str3; str3 = str2; str2 = str1; str1 = TempStr; UpdateData(FALSE); NUM1 = result; NUM2 = 0.0f; } void CxchCakulatorDlg::OnBnClickedButtonnum0() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str += L"0"; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonnum1() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str += L"1"; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonnum2() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str += L"2"; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonnum3() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str += L"3"; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonnum4() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str += L"4"; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonnum5() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str += L"5"; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonnum6() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str += L"6"; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonnum7() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str += L"7"; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonnum8() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str += L"8"; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonnum9() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str += L"9"; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonback() //Back { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); if (!str.IsEmpty()) { str = str.Left(str.GetLength() - 1); } UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonclear() //Clear { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str = L""; NUM1 = 0.0f; NUM2 = 0.0f; Flag = FLAG_ADD; UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonpoint() //小数点 { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); //如果没有小数点,则添加小数点;如果有,则会略本次的小数点,保证最多1个 if (-1 == str.Find(L'.')) { str += L"."; } UpdateData(FALSE); } void CxchCakulatorDlg::OnBnClickedButtonadd() //加 { // TODO: 在此添加控件通知处理程序代码 SaveFirstValue(); Flag = FLAG_ADD; } void CxchCakulatorDlg::OnBnClickedButtonsub() //减 { // TODO: 在此添加控件通知处理程序代码 SaveFirstValue(); Flag = FLAG_SUB; } void CxchCakulatorDlg::OnBnClickedButtonmul() //乘 { // TODO: 在此添加控件通知处理程序代码 SaveFirstValue(); Flag = FLAG_MUL; } void CxchCakulatorDlg::OnBnClickedButtondiv() //除 { // TODO: 在此添加控件通知处理程序代码 SaveFirstValue(); Flag = FLAG_DIV; } void CxchCakulatorDlg::OnBnClickedButtonequal() //等于 { // TODO: 在此添加控件通知处理程序代码 Calculator(); } void CxchCakulatorDlg::OnBnClickedClearall() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); str = L""; str1 = L""; str2 = L""; str3 = L""; str4 = L""; str5 = L""; NUM1 = 0.0f; NUM2 = 0.0f; Flag = FLAG_SUB; UpdateData(FALSE); }
1、结果展示:
新人一枚,主要还是看B站学的,但也稍微有了一些新的认识吧!希望后面会有更大的进步!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。