程序设计实践
设计报告
课题名称:计算器设计
学生姓名:
班 级:
班内序号:
学 号:
日 期:20##年5月10日星期六
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 CcalculatorDlg::OnBnClickedBtn1()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("1");
}
此模块处理的是程序如何响应鼠标的单击,主要由消息映射和消息处理函数两部组成。
(3)运算函数:
例如:
void CcalculatorDlg::Compute(char chOper)
{
UpdateData(TRUE);
m_nTemp2=(float)atof(m_strResult);
switch(chOper)
{
case '+':
m_nTemp2=m_nTemp1+m_nTemp2; break;
case '-':
m_nTemp2=m_nTemp1-m_nTemp2; break;
case '*':
m_nTemp2=m_nTemp1*m_nTemp2; break;
case '/':
m_nTemp2=m_nTemp1/m_nTemp2; break;
case '%':
{
int n1=(int)m_nTemp1;
int n2=(int)m_nTemp2;
m_nTemp2=(float)(n1%n2); break;
}
case'=':
m_nTemp2=m_nTemp1; break;
}
m_nTemp1=m_nTemp2;
m_strResult.Format("%f",m_nTemp2);
m_IsFirstNum=TRUE;
UpdateData(FALSE);
}
此模块是本实验的核心内容,它控制着整个程序的逻辑功能,它所实现的主要是逻辑运算以及数据交换。
[2] 类关系图及描述
在calculatorDlg.h中设置CcalculatorDlg类,如下所示:
class CcalculatorDlg : public CDialog
{
// 构造
public:
CcalculatorDlg(CWnd* pParent = NULL); // 标准构造函数
float m_nTemp1; // 保存第一个操作数
float m_nTemp2; // 保存第二个操作数
char m_chOper; // 保存输入的运算符
bool m_IsFirstNum; // 记录按下操作符后的状态
void Compute(char chOper); // 四则运算函数
void ClickNum(const char* strNum); // 数字输入函数
// 对话框数据
enum { IDD = IDD_CALCULATOR_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton15();
afx_msg void OnBnClickedButton18();
afx_msg void OnBnClickedBtn1();
CString m_strResult;
afx_msg void OnBnClickedBtn0();
afx_msg void OnBnClickedBtn2();
afx_msg void OnBnClickedBtn3();
afx_msg void OnBnClickedBtn4();
afx_msg void OnBnClickedBtn5();
afx_msg void OnBnClickedBtn6();
afx_msg void OnBnClickedBtn7();
afx_msg void OnBnClickedBtn8();
afx_msg void OnBnClickedBtn9();
afx_msg void OnBnClickedBtnAdd();
afx_msg void OnBnClickedBtnSub();
afx_msg void OnBnClickedBtnMult();
afx_msg void OnBnClickedBtnDiv();
afx_msg void OnBnClickedBtnMod();
afx_msg void OnBnClickedBtnCe();
afx_msg void OnBnClickedBtnC();
afx_msg void OnBnClickedBtnResult();
afx_msg void OnBnClickedBtnSign();
afx_msg void OnBnClickedBtnSq();
afx_msg void OnBnClickedBtnAbs();
afx_msg void OnBnClickedBtnPoint();
afx_msg void OnBnClickedBtnSin();
afx_msg void OnBnClickedBtnCos();
afx_msg void OnBnClickedBtnUsd();
};
[3] 程序流程图及描述
2.3 关键算法分析
算法1:ClickNum
[1] 算法功能
实现单击数字输入的功能。
[2] 算法基本思想
通过单击数字,改变与编辑框关联的变量m_strResult,以实现操作数的输入。
[3] 算法空间、时间复杂度分析
时间复杂度为O(1)。
[4] 代码逻辑
void CcalculatorDlg::ClickNum(const char *strNum)
{
UpdateData(TRUE);
if(m_IsFirstNum)
{
m_strResult="";
m_IsFirstNum=FALSE;
}
m_strResult=m_strResult+strNum;
UpdateData(FALSE);
}
算法2:Compute
[1] 算法功能
实现四则运算。
[2] 算法基本思想
单击运算符按钮,系统从编辑框读取操作数,根据运算符作相应的运算,再将结果信息传递给编辑框显示。
[3] 算法空间、时间复杂度分析
时间复杂度为O(1)。
[4] 代码逻辑
void CcalculatorDlg::Compute(char chOper)
{
UpdateData(TRUE);
m_nTemp2=(float)atof(m_strResult);
switch(chOper)
{
case '+':
m_nTemp2=m_nTemp1+m_nTemp2; break;
case '-':
m_nTemp2=m_nTemp1-m_nTemp2; break;
case '*':
m_nTemp2=m_nTemp1*m_nTemp2; break;
case '/':
m_nTemp2=m_nTemp1/m_nTemp2; break;
case '%':
{
int n1=(int)m_nTemp1;
int n2=(int)m_nTemp2;
m_nTemp2=(float)(n1%n2); break;
}
case'=':
m_nTemp2=m_nTemp1; break;
}
m_nTemp1=m_nTemp2;
m_strResult.Format("%f",m_nTemp2);
m_IsFirstNum=TRUE;
UpdateData(FALSE);
}
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
源代码:
// calculatorDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "calculator.h"
#include "calculatorDlg.h"
#include<math.h>
static float pi=3.141592654;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CcalculatorDlg 对话框
CcalculatorDlg::CcalculatorDlg(CWnd* pParent /*=NULL*/)
: CDialog(CcalculatorDlg::IDD, pParent)
, m_strResult(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_nTemp1=0;
m_nTemp2=0;
m_chOper=' ';
m_IsFirstNum=TRUE;
}
void CcalculatorDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_RESULT, m_strResult);
}
BEGIN_MESSAGE_MAP(CcalculatorDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BTN_1, &CcalculatorDlg::OnBnClickedBtn1)
ON_BN_CLICKED(IDC_BTN_0, &CcalculatorDlg::OnBnClickedBtn0)
ON_BN_CLICKED(IDC_BTN_2, &CcalculatorDlg::OnBnClickedBtn2)
ON_BN_CLICKED(IDC_BTN_3, &CcalculatorDlg::OnBnClickedBtn3)
ON_BN_CLICKED(IDC_BTN_4, &CcalculatorDlg::OnBnClickedBtn4)
ON_BN_CLICKED(IDC_BTN_5, &CcalculatorDlg::OnBnClickedBtn5)
ON_BN_CLICKED(IDC_BTN_6, &CcalculatorDlg::OnBnClickedBtn6)
ON_BN_CLICKED(IDC_BTN_7, &CcalculatorDlg::OnBnClickedBtn7)
ON_BN_CLICKED(IDC_BTN_8, &CcalculatorDlg::OnBnClickedBtn8)
ON_BN_CLICKED(IDC_BTN_9, &CcalculatorDlg::OnBnClickedBtn9)
ON_BN_CLICKED(IDC_BTN_ADD, &CcalculatorDlg::OnBnClickedBtnAdd)
ON_BN_CLICKED(IDC_BTN_SUB, &CcalculatorDlg::OnBnClickedBtnSub)
ON_BN_CLICKED(IDC_BTN_MULT, &CcalculatorDlg::OnBnClickedBtnMult)
ON_BN_CLICKED(IDC_BTN_DIV, &CcalculatorDlg::OnBnClickedBtnDiv)
ON_BN_CLICKED(IDC_BTN_MOD, &CcalculatorDlg::OnBnClickedBtnMod)
ON_BN_CLICKED(IDC_BTN_CE, &CcalculatorDlg::OnBnClickedBtnCe)
ON_BN_CLICKED(IDC_BTN_C, &CcalculatorDlg::OnBnClickedBtnC)
ON_BN_CLICKED(IDC_BTN_RESULT, &CcalculatorDlg::OnBnClickedBtnResult)
ON_BN_CLICKED(IDC_BTN_SIGN, &CcalculatorDlg::OnBnClickedBtnSign)
ON_BN_CLICKED(IDC_BTN_SQ, &CcalculatorDlg::OnBnClickedBtnSq)
ON_BN_CLICKED(IDC_BTN_ABS, &CcalculatorDlg::OnBnClickedBtnAbs)
ON_BN_CLICKED(IDC_BTN_POINT, &CcalculatorDlg::OnBnClickedBtnPoint)
ON_BN_CLICKED(IDC_BTN_SIN, &CcalculatorDlg::OnBnClickedBtnSin)
ON_BN_CLICKED(IDC_BTN_COS, &CcalculatorDlg::OnBnClickedBtnCos)
ON_BN_CLICKED(IDC_BTN_USD, &CcalculatorDlg::OnBnClickedBtnUsd)
END_MESSAGE_MAP()
// CcalculatorDlg 消息处理程序
BOOL CcalculatorDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
return TRUE; // 除非将焦点设置到控件,否则返回TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的MFC 应用程序,
// 这将由框架自动完成。
void CcalculatorDlg::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
{
CDialog::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CcalculatorDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CcalculatorDlg::Compute(char chOper)
{
UpdateData(TRUE);
m_nTemp2=(float)atof(m_strResult);
switch(chOper)
{
case '+':
m_nTemp2=m_nTemp1+m_nTemp2; break;
case '-':
m_nTemp2=m_nTemp1-m_nTemp2; break;
case '*':
m_nTemp2=m_nTemp1*m_nTemp2; break;
case '/':
m_nTemp2=m_nTemp1/m_nTemp2; break;
case '%':
{
int n1=(int)m_nTemp1;
int n2=(int)m_nTemp2;
m_nTemp2=(float)(n1%n2); break;
}
case'=':
m_nTemp2=m_nTemp1; break;
}
m_nTemp1=m_nTemp2;
m_strResult.Format("%f",m_nTemp2);
m_IsFirstNum=TRUE;
UpdateData(FALSE);
}
void CcalculatorDlg::ClickNum(const char *strNum)
{
UpdateData(TRUE);
if(m_IsFirstNum)
{
m_strResult="";
m_IsFirstNum=FALSE;
}
m_strResult=m_strResult+strNum;
UpdateData(FALSE);
}
void CcalculatorDlg::OnBnClickedBtn1()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("1");
}
void CcalculatorDlg::OnBnClickedBtn0()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("0");
}
void CcalculatorDlg::OnBnClickedBtn2()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("2");
}
void CcalculatorDlg::OnBnClickedBtn3()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("3");
}
void CcalculatorDlg::OnBnClickedBtn4()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("4");
}
void CcalculatorDlg::OnBnClickedBtn5()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("5");
}
void CcalculatorDlg::OnBnClickedBtn6()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("6");
}
void CcalculatorDlg::OnBnClickedBtn7()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("7");
}
void CcalculatorDlg::OnBnClickedBtn8()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("8");
}
void CcalculatorDlg::OnBnClickedBtn9()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum("9");
}
void CcalculatorDlg::OnBnClickedBtnAdd()
{
// TODO: 在此添加控件通知处理程序代码
Compute(m_chOper);
m_chOper='+';
}
void CcalculatorDlg::OnBnClickedBtnSub()
{
// TODO: 在此添加控件通知处理程序代码
Compute(m_chOper);
m_chOper='-';
}
void CcalculatorDlg::OnBnClickedBtnMult()
{
// TODO: 在此添加控件通知处理程序代码
Compute(m_chOper);
m_chOper='*';
}
void CcalculatorDlg::OnBnClickedBtnDiv()
{
// TODO: 在此添加控件通知处理程序代码
Compute(m_chOper);
m_chOper='/';
}
void CcalculatorDlg::OnBnClickedBtnMod()
{
// TODO: 在此添加控件通知处理程序代码
Compute(m_chOper);
m_chOper='%';
}
void CcalculatorDlg::OnBnClickedBtnResult()
{
// TODO: 在此添加控件通知处理程序代码
Compute(m_chOper);
m_chOper='=';
}
void CcalculatorDlg::OnBnClickedBtnCe()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
m_strResult=m_strResult.Left(m_strResult.GetLength()-1);
UpdateData(FALSE);
}
void CcalculatorDlg::OnBnClickedBtnC()
{
// TODO: 在此添加控件通知处理程序代码
m_nTemp1=0;
m_nTemp2=0;
m_chOper=' ';
m_strResult="";
m_IsFirstNum=TRUE;
UpdateData(FALSE);
}
void CcalculatorDlg::OnBnClickedBtnSign()
{
// TODO: 在此添加控件通知处理程序代码
m_nTemp1=atof(m_strResult);
float a=0;
m_nTemp2=(a-m_nTemp1);
m_nTemp1=m_nTemp2;
m_strResult.Format("%f",m_nTemp2);
m_IsFirstNum=TRUE;
UpdateData(FALSE);
}
void CcalculatorDlg::OnBnClickedBtnSq()
{
// TODO: 在此添加控件通知处理程序代码
m_nTemp1=atof(m_strResult);
m_nTemp2=m_nTemp1*m_nTemp1;
m_nTemp1=m_nTemp2;
m_strResult.Format("%f",m_nTemp2);
m_IsFirstNum=TRUE;
UpdateData(FALSE);
}
void CcalculatorDlg::OnBnClickedBtnAbs()
{
// TODO: 在此添加控件通知处理程序代码
m_nTemp1=atof(m_strResult);
m_nTemp2=abs(m_nTemp1);
m_nTemp1=m_nTemp2;
m_strResult.Format("%f",m_nTemp2);
m_IsFirstNum=TRUE;
UpdateData(FALSE);
}
void CcalculatorDlg::OnBnClickedBtnPoint()
{
// TODO: 在此添加控件通知处理程序代码
ClickNum(".");
}
void CcalculatorDlg::OnBnClickedBtnSin()
{
// TODO: 在此添加控件通知处理程序代码
m_nTemp1=atof(m_strResult);
m_nTemp2=sin((m_nTemp1/180)*pi);
m_nTemp1=m_nTemp2;
m_strResult.Format("%f",m_nTemp2);
m_IsFirstNum=TRUE;
UpdateData(FALSE);
}
void CcalculatorDlg::OnBnClickedBtnCos()
{
// TODO: 在此添加控件通知处理程序代码
m_nTemp1=atof(m_strResult);
m_nTemp2=cos((m_nTemp1/180)*pi);
m_nTemp1=m_nTemp2;
m_strResult.Format("%f",m_nTemp2);
m_IsFirstNum=TRUE;
UpdateData(FALSE);
}
void CcalculatorDlg::OnBnClickedBtnUsd()
{
// TODO: 在此添加控件通知处理程序代码
m_nTemp1=atof(m_strResult);
m_nTemp2=1/m_nTemp1;
m_nTemp1=m_nTemp2;
m_strResult.Format("%f",m_nTemp2);
m_IsFirstNum=TRUE;
UpdateData(FALSE);
}
计算机科学与技术学部面向对象程序课程设计题目计算器学部计算机科学与技术班级指导教师姓名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关键功能的实现…
设计题目及要求设计题目及要求设计题目及要求设计题目及要求1.综合应用实例——学生成绩管理编写一个菜单驱动的学生成绩管理程序。实现如…