程序设计实践
设计报告
课题名称:简易计算器设计与实现
学生姓名:
班 级:
班内序号:
学 号:
日 期:
1. 课题概述
1.1课题目标和主要内容
本案例以编写基于MFC的简易计算器软件为例,通过学习MFC事件驱动机制、MFC界面设计、MFC控件使用,并掌握MFC应用程序的设计方法,独立完成一个MFC的一个MFC的应用程序。本案例的重点是学习如何使用MFC基本控件和事件驱动机制完成一个Windows下交互式应用软件。本次实验所用的开发平台为Visual Studio 2008。
1.2系统的主要功能
基本功能
单击数字键,显示当前数值
单击“+”、“-”、“*”、“/”建进行运算
单击“=”,显示运算结果
单击“C”,清楚已有结果
进行连续四则运算
扩展功能
进行浮点运算
进行平方、绝对值、倒数运算
进行三角函数运算
2. 系统设计
2.1 系统总体框架
2.2 系统详细设计
[1] 模块划分图及描述
(1)对话框:
此模块实现的是与用户的交互,本案例使用了两类控件:编辑框和按钮。
(2)事件驱动函数:
例如:
void CdckcalculatorDlg::OnBnClickedBtn1()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("1");
}
此模块处理的是程序如何响应鼠标的单击,主要由消息映射和消息处理函数两部组成。
(3)运算函数:
例如:
void CdckCalculatorDlg::onButtonN(int n)
{
if( m_coff == 1.0)
m_second = m_second*10 + n;//作为整数输入数字时骸
else
{ m_second = m_second + n*m_coff; //作为小数输入数字
m_coff *= 0.1; }
UpdateDisplay(m_second);//更新编辑框的数字显示
}
此模块是本实验的核心内容,它控制着整个程序的逻辑功能,它所实现的主要是逻辑运算以及数据交换。
[2] 类关系图及描述
在calculatorDlg.h中设置CcalculatorDlg类,如下所示:
// dckCalculatorDlg.h : 头文件
//
#pragma once
// CdckCalculatorDlg 对话框
class CdckCalculatorDlg : public CDialog
{
// 构造
public:
CdckCalculatorDlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
enum { IDD = IDD_DCKCALCULATOR_DIALOG };
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()
public:
double m_first;
public:
double m_second;
public:
CString m_operator;
public:
double m_coff;
public:
CString m_display;
public:
void UpdateDisplay(double dck);
public:
void Calculate(void);
public:
afx_msg void OnBnClickedButton0();
public:
afx_msg void OnBnClickedButton1();
public:
afx_msg void OnBnClickedButton2();
public:
afx_msg void OnBnClickedButton3();
public:
afx_msg void OnBnClickedButton4();
public:
afx_msg void OnBnClickedButton5();
public:
afx_msg void OnBnClickedButton6();
public:
afx_msg void OnBnClickedButton7();
public:
afx_msg void OnBnClickedButton8();
public:
afx_msg void OnBnClickedButton9();
public:
afx_msg void OnBnClickedButtonSign();
public:
afx_msg void OnBnClickedButtonPoint();
public:
afx_msg void OnBnClickedButtonAdd();
public:
void onButtonN(int n);
public:
afx_msg void OnBnClickedButtonMinus();
public:
afx_msg void OnBnClickedButtonMutiply();
public:
afx_msg void OnBnClickedButtonDiv();
public:
afx_msg void OnBnClickedButtonClear();
public:
afx_msg void OnBnClickedButtonSqrt();
public:
afx_msg void OnBnClickedButtonReci();
public:
afx_msg void OnBnClickedButtonEqual();
public:
afx_msg void OnBnClickedExp();
public:
afx_msg void OnBnClickedCos();
public:
afx_msg void OnBnClickedSin();
public:
afx_msg void OnBnClickedLn();
public:
afx_msg void OnBnClickedLog();
public:
afx_msg void OnBnClickedTan();
public:
double m_PI;
public:
double temp;
};
[3] 程序流程图及描述
2.3 关键算法分析
算法1:ClickNum
[1] 算法功能
实现单击数字输入的功能。
[2] 算法基本思想
通过单击数字,改变与编辑框关联的变量m_strResult,以实现操作数的输入。
[3] 算法空间、时间复杂度分析
时间复杂度为O(1)。
[4] 代码逻辑
void CdckCalculatorDlg::onButtonN(int n)
{
if( m_coff == 1.0)
m_second = m_second*10 + n;//作为整数输入数字时
else
{ m_second = m_second + n*m_coff; //作为小数输入数字
m_coff *= 0.1; }
UpdateDisplay(m_second);//更新编辑框的数字显示
}
算法2:Compute
[1] 算法功能
实现四则运算。
[2] 算法基本思想
单击运算符按钮,系统从编辑框读取操作数,根据运算符作相应的运算,再将结果信息传递给编辑框显示。
[3] 算法空间、时间复杂度分析
时间复杂度为O(1)。
[4] 代码逻辑
void CdckCalculatorDlg::Calculate(void)
{ switch(m_operator.GetAt(0))
{ case '+': m_first+=m_second;break;
case '-': m_first-=m_second;break;
case '*': m_first*=m_second;break;
case '/':
if(fabs(m_second)<=0.000001)
{m_display="除数不能为0";
UpdateData(false);
return; }
m_first/=m_second;break;
}
m_second=0.0;
m_coff=1.0;
m_operator=_T("+");
UpdateDisplay(m_first);//更新编辑框显示内容
}
3. 程序运行结果分析
通过按钮实现数字输入和运算,编辑框显示结果。
4. 总结
4.1课题的难点和关键点
该课题的难点主要是浮点计算的实现和单双目运算的区分。
开始时将类中的操作数都设置为整型,可以实现最基本的整数四则运算,但是在之后实现扩展功能时发现整数无法很好得实现所要求的功能,于是便要求计算器能够实现浮点输入和运算。最简单的方法便是将操作数设置为float类型。但值得注意的是,当改变了操作数的类型后,相应的一些语句也需要做修改。比如,从编辑框读取的函数atoi要改为atof,类似的,m_strResult.Format("%d",m_nTemp2);中的”%d”要改为”%f”。最后,由于取余运算无法处理float类型的变量,所以在编写这一部分的程序时,需要将操作数转化为整型,再强制转化为float类型。
4.2 本课题的评价
此课题主要由按钮和编辑框组成,是一个最基本的MFC程序。此课题的实践让我们在之前面向过程的编程基础上进一步接触了面向对象的程序设计。
而在此次课题的设计中,我的代码也有一些需要改进的地方。比如,在实现如平方,三角等单目运算的时候,我采用了另写函数的方法,然而,这些运算完全可以用之前定义的compute函数完成,只需要在其中的switch逻辑中加入相应的运算即可。这样可以减少程序运行所需的内存空间。
4.3心得体会
在实践中,面向对象的程序设计远比面向过程的程序设计实用得多,而C++语言平台已经为我们提供了很多实用的框架,让我们的设计更聚焦与功能的优化和创新。当然,回归到语言上,语法,结构,逻辑都是相同的,所以,坚实的语言基础是十分必要的。另外,在程序设计的过程中,我们还需要有排错能力和创新的意识。
5. 参考文献
[1]C++高级语言程序设计案例与实践辅导/徐惠民主编——北京:人民邮电出版社,2012.3
源代码:
// dckCalculatorDlg.cpp : 实害?现?文?件t
//
#include "stdafx.h"
#include "dckCalculator.h"
#include "dckCalculatorDlg.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用?于?应畖用?程ì序ò“°关?于?”±菜?单蹋?项?的? CAboutDlg 对?话°框ò
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对?话°框ò数簓据Y
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支§持?
// 实害?现?
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CdckCalculatorDlg 对?话°框ò
// CdckCalculatorDlg 对?话°框ò的?构1造ì函ˉ数簓
CdckCalculatorDlg::CdckCalculatorDlg(CWnd* pParent /*=NULL*/)
: CDialog(CdckCalculatorDlg::IDD, pParent)
, m_first(0.0)
, m_second(0.0)
, m_operator(_T("+"))
, m_coff(1.0)
, m_display(_T("0.0"))
, m_PI(3.14159265358979323846)
, temp(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CdckCalculatorDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_DISPLAY, m_display);
}
BEGIN_MESSAGE_MAP(CdckCalculatorDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON0, &CdckCalculatorDlg::OnBnClickedButton0)
ON_BN_CLICKED(IDC_BUTTON1, &CdckCalculatorDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &CdckCalculatorDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON3, &CdckCalculatorDlg::OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON4, &CdckCalculatorDlg::OnBnClickedButton4)
ON_BN_CLICKED(IDC_BUTTON5, &CdckCalculatorDlg::OnBnClickedButton5)
ON_BN_CLICKED(IDC_BUTTON6, &CdckCalculatorDlg::OnBnClickedButton6)
ON_BN_CLICKED(IDC_BUTTON7, &CdckCalculatorDlg::OnBnClickedButton7)
ON_BN_CLICKED(IDC_BUTTON8, &CdckCalculatorDlg::OnBnClickedButton8)
ON_BN_CLICKED(IDC_BUTTON9, &CdckCalculatorDlg::OnBnClickedButton9)
ON_BN_CLICKED(IDC_BUTTON_SIGN, &CdckCalculatorDlg::OnBnClickedButtonSign)
ON_BN_CLICKED(IDC_BUTTON_POINT, &CdckCalculatorDlg::OnBnClickedButtonPoint)
ON_BN_CLICKED(IDC_BUTTON_ADD, &CdckCalculatorDlg::OnBnClickedButtonAdd)
ON_BN_CLICKED(IDC_BUTTON_MINUS, &CdckCalculatorDlg::OnBnClickedButtonMinus)
ON_BN_CLICKED(IDC_BUTTON_MUTIPLY, &CdckCalculatorDlg::OnBnClickedButtonMutiply)
ON_BN_CLICKED(IDC_BUTTON_DIV, &CdckCalculatorDlg::OnBnClickedButtonDiv)
ON_BN_CLICKED(IDC_BUTTON_CLEAR, &CdckCalculatorDlg::OnBnClickedButtonClear)
ON_BN_CLICKED(IDC_BUTTON_SQRT, &CdckCalculatorDlg::OnBnClickedButtonSqrt)
ON_BN_CLICKED(IDC_BUTTON_RECI, &CdckCalculatorDlg::OnBnClickedButtonReci)
ON_BN_CLICKED(IDC_BUTTON_EQUAL, &CdckCalculatorDlg::OnBnClickedButtonEqual)
ON_BN_CLICKED(IDC_EXP, &CdckCalculatorDlg::OnBnClickedExp)
ON_BN_CLICKED(IDC_COS, &CdckCalculatorDlg::OnBnClickedCos)
ON_BN_CLICKED(IDC_SIN, &CdckCalculatorDlg::OnBnClickedSin)
ON_BN_CLICKED(IDC_LN, &CdckCalculatorDlg::OnBnClickedLn)
ON_BN_CLICKED(IDC_LOG, &CdckCalculatorDlg::OnBnClickedLog)
ON_BN_CLICKED(IDC_TAN, &CdckCalculatorDlg::OnBnClickedTan)
END_MESSAGE_MAP()
// CdckCalculatorDlg 消?息¢处鋦理え?程ì序ò
BOOL CdckCalculatorDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 将?“°关?于?..”±菜?单蹋?项?添?加ó到?系μ统?菜?单蹋?中D。£
// IDM_ABOUTBOX 必?须?在ú系μ统?命ü令?范?围§内ú。£
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设Θ?置?此?对?话°框ò的?图?标括?。£当獭?应畖用?程ì序ò主÷窗洹?口ú不?是?对?话°框ò时骸?,?框ò架ü将?自?动ˉ
// 执′行D此?操ù作痢?
SetIcon(m_hIcon, TRUE); // 设Θ?置?大洙?图?标括?
SetIcon(m_hIcon, FALSE); // 设Θ?置?小?图?标括?
// TODO: 在ú此?添?加ó额?外猘的?初?始?化ˉ代洙?码?
return TRUE; // 除y非?将?焦1点?设Θ?置?到?控?件t,?否?则ò返う?回? TRUE
}
void CdckCalculatorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 如?果?向ò对?话°框ò添?加ó最?小?化ˉ按恪?钮¥,?则ò需è要癮下?面?的?代洙?码?
// 来ぁ?绘?制?该?图?标括?。£对?于?使?用?文?档苔?视酣?图?模£型í的? MFC 应畖用?程ì序ò,?
// 这a将?由?框ò架ü自?动ˉ完?成é。£
void CdckCalculatorDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用?于?绘?制?的?设Θ?备?上?下?文?
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使?图?标括?在ú工¤作痢?矩?形?中D居ó中D
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
{
CDialog::OnPaint();
}
}
//当獭?用?户§拖?动ˉ最?小?化ˉ窗洹?口ú时骸?系μ统?调獭?用?此?函ˉ数簓取?得?光a标括?显?示?。£
//
HCURSOR CdckCalculatorDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
//在ú编括?辑-框ò中D显?示?数簓据Y
void CdckCalculatorDlg::UpdateDisplay(double dck)
{
m_display.Format(_T("%f"),dck);
int i=m_display.GetLength();
while(m_display.GetAt(i-1)=='0') //格?式?化ˉ输?出?,将?输?出?结á果?后ó的?零?截?去ǎ?
{ m_display.Delete(i-1,1); i--; }
UpdateData(false);//更ü新?编括?辑-框ò变?量?m_display
}
//计?算?结á果?
void CdckCalculatorDlg::Calculate(void)
{//将?前°一?次?数簓据Y与?当獭?前°数簓据Y进?行D运?算?,?作痢?为a下?次?的?第台?一?操ù作痢?数簓,?并¢在ú编括?辑-框ò显?示?。£
switch(m_operator.GetAt(0))
{ case '+': m_first+=m_second;break;
case '-': m_first-=m_second;break;
case '*': m_first*=m_second;break;
case '/':
if(fabs(m_second)<=0.000001)
{m_display="除y数簓不?能ü为a0";
UpdateData(false);
return; }
m_first/=m_second;break;
}
m_second=0.0;
m_coff=1.0;
m_operator=_T("+");
UpdateDisplay(m_first);//更ü新?编括?辑-框ò显?示?内ú容╕
}
void CdckCalculatorDlg::onButtonN(int n)
{
if( m_coff == 1.0)
m_second = m_second*10 + n;//作痢?为a整?数簓输?入?数簓字?时骸?
else
{ m_second = m_second + n*m_coff; //作痢?为a小?数簓输?入?数簓字?
m_coff *= 0.1; }
UpdateDisplay(m_second);//更ü新?编括?辑-框ò的?数簓字?显?示?
}
void CdckCalculatorDlg::OnBnClickedButton0()
{
onButtonN(0);
}
void CdckCalculatorDlg::OnBnClickedButton1()
{
onButtonN(1);
}
void CdckCalculatorDlg::OnBnClickedButton2()
{
onButtonN(2);
}
void CdckCalculatorDlg::OnBnClickedButton3()
{
onButtonN(3);
}
void CdckCalculatorDlg::OnBnClickedButton4()
{
onButtonN(4);
}
void CdckCalculatorDlg::OnBnClickedButton5()
{
onButtonN(5);
}
void CdckCalculatorDlg::OnBnClickedButton6()
{
onButtonN(6);
}
void CdckCalculatorDlg::OnBnClickedButton7()
{
onButtonN(7);
}
void CdckCalculatorDlg::OnBnClickedButton8()
{
onButtonN(8);
}
void CdckCalculatorDlg::OnBnClickedButton9()
{
onButtonN(9);
}
// "+/-"
void CdckCalculatorDlg::OnBnClickedButtonSign()
{
m_second = -m_second;
UpdateDisplay(m_second);
}
// "."
void CdckCalculatorDlg::OnBnClickedButtonPoint()
{
m_coff = 0.1 ;
}
// "+"
void CdckCalculatorDlg::OnBnClickedButtonAdd()
{
Calculate();
m_operator="+";
}
// "-"
void CdckCalculatorDlg::OnBnClickedButtonMinus()
{
Calculate();
m_operator="-";
}
// "x"
void CdckCalculatorDlg::OnBnClickedButtonMutiply()
{
Calculate();
m_operator="*";
}
// "/"
void CdckCalculatorDlg::OnBnClickedButtonDiv()
{
Calculate();
m_operator.Format(_T("%s"),"/");
}
// "C"
void CdckCalculatorDlg::OnBnClickedButtonClear()
{
m_first=0.0;
m_second=0.0;
m_operator = "+";
m_coff = 1.0;
UpdateDisplay(0.0);
}
// "sqrt"
void CdckCalculatorDlg::OnBnClickedButtonSqrt()
{
if( m_second==0)
{ m_first=sqrt(m_first);
UpdateDisplay(m_first); }
else
{ m_second=sqrt(m_second);
UpdateDisplay(m_second); }
}
// "1/x"
void CdckCalculatorDlg::OnBnClickedButtonReci()
{
if(fabs(m_second)<0.000001 && fabs(m_first)<0.000001)
{m_display = "除y数簓不?能ü为a零?";
UpdateData(false);
return; }
if( fabs(m_second)<0.000001)
{ m_first=1.0/m_first;
UpdateDisplay(m_first);
}
else
{ m_second=1.0/m_second;
UpdateDisplay(m_second);
}
}
// "="
void CdckCalculatorDlg::OnBnClickedButtonEqual()
{
Calculate();
}
// "exp"
void CdckCalculatorDlg::OnBnClickedExp()
{
m_second=exp(m_second);
UpdateDisplay(m_second);
}
// "cos"
void CdckCalculatorDlg::OnBnClickedCos()
{
m_second=cos(m_second);
UpdateDisplay(m_second);
}
// "sin"
void CdckCalculatorDlg::OnBnClickedSin()
{
m_second=sin(m_second);
UpdateDisplay(m_second);
}
// "ln"
void CdckCalculatorDlg::OnBnClickedLn()
{
m_second=log(m_second);
UpdateDisplay(m_second);
}
// "log"
void CdckCalculatorDlg::OnBnClickedLog()
{
m_second=log10(m_second);
UpdateDisplay(m_second);
}
// "tan"
void CdckCalculatorDlg::OnBnClickedTan()
{
m_second=tan(m_second);
UpdateDisplay(m_second);
}
计算机科学与技术学部面向对象程序课程设计题目计算器学部计算机科学与技术班级指导教师姓名20xx年6月16日课程设计任务分配表Vis…
C语言集中上机实验报告一123二1需求分析制作一个计算器能够计算四则混合运算以及乘方和开方并显示出正确的结果程序能根据运算符的高低…
课程设计说明书题目计算器程序设计起讫日期20xx年7月3日至20xx年8月6日所在院系软件学院专业机械软件班级042学生姓名偶偶哦…
运城学院单片机课程设计报告课题名称计算器设计单位运城学院所在院系计算机科学与技术系班级0902班指导教师赵润林学生姓名裴立军贺琛王…
MFC计算器课程设计报告地信091指导老师20xx1115一题目利用MFC框架编写简易计算器要求使用MFC框架在VisualStu…
实习名称:用汇编语言实现音乐程序设计专业:计算机科学与技术专业班级:200级计算机科学与技术专业班学号:姓名:指导教师:成绩:2x…
一课题任务及要求要求1掌握数码管移位动态扫描显示的编程方法2掌握矩阵扫描的编程方法3掌握数据在内部运算的编程方法任务1实现最大6位…
武汉理工大学专业课程设计2课程设计说明书目录1基本功能描述12设计思路13软件设计431设计步骤44结论与心得体会127附设计中的…
中南大学本科生课程设计实践设计报告程序设计基础题目学生学号学生姓名指导教师学院专业班级MFC编程科学计算器1104120xx2郭斌…
武汉理工大学专业课程设计2课程设计说明书目录1基本功能描述12设计思路13软件设计431设计步骤432界面设计533关键功能的实现…
实验4计数器及其应用一实验目的1学习用集成触发器构成计数器的方法2掌握中规模集成计数器的使用及功能测试方法二实验原理计数器是一个用…