MFC计算器课程设计报告

时间:2024.3.31

MFC仿windows计算器

设计报告

一.题目:利用MFC框架编写简易计算器

要求使用MFC框架在Visual Studio 6.0环境下编写一个简易的计算器,支持任意位数的加减乘数,正负转换,并且实现BackSpace CE C功能。

二.设计过程

1.         Windows消息处理机制的理解
首先编写程序需要对Windows程序的消息处理机制(Message Handle)有个比较清晰的了解。Windows的程序都是通过消息来传送数据,有不需要用户参与的系统消息,比如异常处理等。还有用户消息,比如鼠标的单击,双击,键盘的键入等。

2.           界面的设计
仿照Windows附件里面的计算器,在资源视图中画好界面,如图:
       
主要使用到Layout菜单中的Align功能对各个按钮进行对其,使界面更加整洁。拖出的控件有上面的一个Edit控件用于显示数字,Button控件用于处理鼠标的消息。

3.         建立的变量,控件的命名,对应的消息处理函数对应表

变量定义:

       double poz; //保存小数点的位置,初始化为1,表示poz-1个小数点。

       double    m_Dis; //Edit控件上需要显示的数字

       BOOL point_flag;  //小数点表示位,判定是否是小数,是小数为1,不是小数为0

       double numfirst; //保存计算过程中的前一个数字,

       double numsecond;//保存计算过程中的第二个数字

       char op;//记录当前的计算符号,可以为’+’,’-’,’*’,’/’,’=’,’c’,’n’

变量初始化:

       poz=1;

       m_Dis = 0.0;

       numfirst=0;

       numsecond=0;

       op=0;

      

4.         设计思路

a)         首先考虑对所有按键分为两类,数字类符号类,0,1,2,3,4,5,6,7,8,9为数字类,+,-,*,/,=为符号类。数字在计算的过程中最多需要保存两个,所以定义了两个double型变量numfirst和numsecond来进行存储。符号需要一个char op来存储。

b)        然后考虑在计算的过程中,numfirst和numsecond的存储状态有三种,一种是numfirst==0 && numsecond==0 也就是程序刚开始运行还没有开始录入数字的状态。二种是numfirst!=0 && numsecond==0 也就是第一个数字已经录入,符号也已经录入时候把m_Dis的值直接赋值给numfirst,第三种是numfirst!=0 &&numsecond!=0,表示可以通过op来把两数合并为一个数。

c)         考虑到该计算器支持连续的计算,比如3.33+1.33*88/96= ?。所以必须在点符号Button也要计算出之前的结果,通过判断op,来计算,把两个数字合并为一个数字,方便下一次运算,功能近似于点=,所以把=也划分到符号类。

d)        因为数字全部使用的是double,键入的数字必须通过一定的处理达到累加的效果,加上小数和整数的处理差异性大,所以分别用point_flag来判断,分别出来小数和整数。

5. 成员函数及其释义

       因为对OnNum0()到OnNum9()的处理函数差异仅在一个数字上,可以通过调用一个共同的函数OnCal(double num)来简化源代码长度,增加模块性。


void CCalcDlg::OnCal(double num)


{    //分三种状态来处理

     if(numfirst!=0 && numsecond!=0)

     {

         if(point_flag==TRUE) //判定为小数

         {

         poz*=0.1; //小数进位

         m_Dis=m_Dis+poz*num;//递增

         UpdateData(false);  //把结果从内存传递到屏幕

         }

         else

         {

              m_Dis=m_Dis*10+num;

              UpdateData(false);

         }

     }

     if(numfirst!=0 && numsecond==0)

     {   

         if(point_flag==TRUE)

         {

              poz*=0.1;

              m_Dis=m_Dis+poz*num;

              UpdateData(false);

         }

         else//判定为整数

         {

              m_Dis=m_Dis*10+num;//递增

              UpdateData(false);

         }

     }

     if(numfirst==0 && numsecond==0)

     {

         if(point_flag==TRUE)

         {

              poz*=0.1;

              m_Dis=m_Dis+poz*num;

              UpdateData(false); 

         }

         else

         {

              m_Dis=m_Dis*10+num;

              UpdateData(false);

         }

     }

}

以OnAdd()为例子讲解符号的处理函数,函数的功能是先判定之前按下字符时op的值,更具op的值来进行相应的运算。

void CCalcDlg::OnAdd()

{    //根据numfirst和numsecond和op的值分为5种状态。

     if(numfirst!=0 && numsecond==0&&op=='+')

     {   

         numsecond=m_Dis;

         numfirst=numfirst+numsecond; //之前按的是加把两个数赋值到前一个数

         m_Dis=numfirst;//赋值给屏幕

         numsecond=0; //从新赋值为0,清空,不影响下一次判断

         UpdateData(FALSE);

         m_Dis=0; //屏幕的值同时清空

     }

     if(numfirst!=0 && numsecond==0&&op=='-')

     {   

         numsecond=m_Dis;

         numfirst=numfirst-numsecond;

         m_Dis=numfirst;

         numsecond=0;

         UpdateData(FALSE);

         m_Dis=0;

     }

     if(numfirst!=0 && numsecond==0&&op=='*')

     {   

         numsecond=m_Dis;

         numfirst=numfirst*numsecond;

         m_Dis=numfirst;

         numsecond=0;

         UpdateData(FALSE);

         m_Dis=0;

     }

     if(numfirst!=0 && numsecond==0&&op=='/')

     {   

         numsecond=m_Dis;

         numfirst=numfirst/numsecond;

         m_Dis=numfirst;

         numsecond=0;

         UpdateData(FALSE);

         m_Dis=0;

     }

     if(numfirst==0 && numsecond==0)

     { //该状态为程序启动还没有开始录入输入的状态

         numfirst=m_Dis; //屏幕的值赋值到numfirst

         UpdateData(FALSE);

         m_Dis=0;

     }

     op='+';  //最后记录最后一个操作是+

     poz=1;//小数点位置归位

     point_flag=FALSE;//默认小数点标志为整数,也就是0,也就是FALSE

}

“+/-“按钮的处理函数

void CCalcDlg::OnNeg()

{

     m_Dis=-m_Dis;//换个符号,其他都一样

     UpdateData(FALSE);

     poz=1;

     point_flag=FALSE;

}

‘.’按钮的处理函数

void CCalcDlg::OnPt()

{

     point_flag=TRUE;  //把标志位改为“小数点”状态

}

“Backspace”按钮的处理

void CCalcDlg::OnBackspace()

{

     //主要通过_gcvt()和strtod()函数进行字符串和浮点数之间的转换

     char buffer[30]; //定义个装字符的数组

     _gcvt(m_Dis,sizeof(m_Dis),buffer);  //把m_Dis存的数字转换为string

     for(int i=0;i<30;i++)

     {

         if(buffer[i]=='.'&& buffer[i+1]==0)//判断是否为整数

         {

              point_flag=FALSE; //标志位设置为“整数位”

              break;

         }

     }

     if(point_flag==TRUE)  //如果是小数

     {

         for(int j=0;j<30;j++)

         {

              if(buffer[j]==0)

              {

                   buffer[j-1]=0; //把’\0’之前的字符赋值为’\0’,就相当于剪掉最后一位

                   break;

              }

         }

     }

     else  //如果是整数

     {

         buffer[i-1]=0; //剪掉’.’之前那位

     }

     m_Dis=strtod(buffer,NULL);//再用strtod弄成浮点数

     UpdateData(FALSE); 

     poz=1;

‘CE’按钮处理函数

void CCalcDlg::OnCe()

{

     if(numfirst!=0 && numsecond==0)//CE只能修改第二个数字

     {

         m_Dis=0;  //把屏幕的值赋值为0

         UpdateData(FALSE);//并显示出来

     }

}

‘C’按钮处理函数

void CCalcDlg::OnClear()

{

     op=NULL; //清空符号

     numfirst=0;//清空第一个数字

     numsecond=0;//清空第二个数字

     point_flag=FALSE;//改为默认整数位

     poz=1;//小数点归位

     m_Dis=0;

     UpdateData(FALSE); //屏幕显示归0

}

键盘响应:

void CCalcDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

{

    switch(nChar)

    {

    case VK_NUMPAD0:

        OnNum0();break;

    case VK_NUMPAD1:

        OnNum1();break;

    case VK_NUMPAD2:

        OnNum2();break;

    case VK_NUMPAD3:

        OnNum3();break;

    case VK_NUMPAD4:

        OnNum4();break;

    case VK_NUMPAD5:

        OnNum5();break;

    case VK_NUMPAD6:

        OnNum6();break;

    case VK_NUMPAD7:

        OnNum7();break;

    case VK_NUMPAD8:

        OnNum8();break;

    case VK_NUMPAD9:

        OnNum9();break;

    case VK_ADD:

        OnAdd();break;

    case VK_SUBTRACT:

        OnMin();break;

    case VK_MULTIPLY:

        OnMul();break;

    case VK_DIVIDE:

        OnDiv();break;

    case VK_BACK:

        OnBackspace();break;

    case VK_DECIMAL:

        OnPt();break;

    case VK_DELETE:

        OnBackspace();break;

    case VK_RETURN:

        OnEqu();break;

    }

    CDialog::OnKeyDown(nChar, nRepCnt, nFlags);

}

BOOL CCalcDlg::PreTranslateMessage(MSG* pMsg)

{

    SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam); 

    return CDialog::PreTranslateMessage(pMsg);

}

总结:

本次MFC计算器的制作,学习到了MFC基本的编程方法,增加了小组开发的团结协作能力。对OOP编程的理解进一步加深。但是程序仍然没存在一定的问题,比如除数不能为0的Exception handle,符号键多次点击结果混乱。由于时间仓促,如果有更多的时间,必定这些问题会迎刃而解。通过这次课程设计,以后Windows 应用程序势必会轻车熟路。


第二篇:李晓奇 丁健华 吴继超等MFC计算器课程设计报告


MFC表达式计算器课程设计报告

     班    级:    5班     

  学生姓名及学号:丁健华(02011507)

              李晓奇(02011513)

              吴继超(02011516)

              

          完成日期:20121013

小组成员及分工:

李晓奇(主要负责Calculate.cpp代码的编写)

李晓奇(主要负责界面的设计和实现、辅助代码的编写)

丁健华(主要负责功能的改进与创新、辅助代码的编写)

丁健华(主要负责代码的链接、辅助代码的编写)

吴继超(主要负责报告的书写、辅助代码的编写)

 题目:利用MFC框架编写简易表达式计算器

【分析】

一.设计过程

1.Windows消息处理机制的理解

首先编写程序需要对Windows程序的消息处理机制(Message Handle)有个比较清晰的了解。Windows的程序都是通过消息来传送数据,有不需要用户参与的系统消息,比如异常处理等。还有用户消息,比如鼠标的单击,双击,键盘的键入等。

2.界面的设计
1)界面的初步设计

仿照Windows附件里面的计算器,在资源视图中画好界面,如图:

2)修改每个static的属性

3)修改每个button的属性

结果如下图:


4)修改每个button的处理机制

在类向导Classwizard窗口中进行,如下图:

其他button按钮的修改类似

5)修改每个edit的类型和名称

在类向导Classwizard窗口中进行:

单击Add Variable按钮,在如下窗口中进行修改

其他edit的修改类似

最终结果如下:

注:主要使用到Layout菜单中的Align功能对各个按钮进行对齐,使界面更加整洁。拖出的控件有上面的一个Edit控件用于显示数字,Button控件用于处理鼠标的消息。

6)系统菜单的添加

在Menu的IDR_MENU1中添加系统菜单:

同理在“帮助”菜单中添加“关于”。

二.  设计步骤

1. 添加头文件

将Calculate.cpp(见附录)改为Calculate.h将其添加到计算器Dlg.cpp : implementation file中,如下:#include "Calculate.h"。

2.成员函数及其释义:

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

       CDialog::DoDataExchange(pDX);

       //{{AFX_DATA_MAP(CAboutDlg)

       //}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

       //{{AFX_MSG_MAP(CAboutDlg)

       //}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CMyDlg dialog

CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)

       : CDialog(CMyDlg::IDD, pParent)

{

       //{{AFX_DATA_INIT(CMyDlg)

              // NOTE: the ClassWizard will add member initialization here

       //}}AFX_DATA_INIT

       // Note that LoadIcon does not require a subsequent DestroyIcon in Win32

       m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}

void CMyDlg::DoDataExchange(CDataExchange* pDX)

{

       CDialog::DoDataExchange(pDX);

       //{{AFX_DATA_MAP(CMyDlg)

       DDX_Control(pDX, IDC_EDIT3, m_time);

       DDX_Control(pDX, IDC_EDIT2, m_result);

       DDX_Control(pDX, IDC_EDIT1, m_input);

       //}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CMyDlg, CDialog)

       //{{AFX_MSG_MAP(CMyDlg)

       ON_WM_SYSCOMMAND()

       ON_WM_PAINT()

       ON_WM_QUERYDRAGICON()

       ON_BN_CLICKED(IDC_BUTTON1, OnButton1)

       ON_BN_CLICKED(IDC_BUTTON2, OnButton2)

       ON_WM_TIMER()

       ON_BN_CLICKED(IDC_BUTTON3, OnButton3)

       ON_COMMAND(ID_ABOUT, OnAbout)

       ON_COMMAND(ID_QUIT, OnQuit)

       //}}AFX_MSG_MAP

END_MESSAGE_MAP()

////////////////////////////////////////////////////////////////////////////

// CMyDlg message handlers

3.OnButton1()按钮的处理函数

双击“等于(=)”按钮,添加如下代码:

void CMyDlg::OnButton1()

{

       // TODO: Add your control notification handler code here

     CString str;

        char *ch;

        m_input.GetWindowText(str);

        ch = (LPSTR)(LPCTSTR)str;

        char ch2[50];

        strcpy(ch2,ch);

        Cal a(ch2);

        if(!a.OK)

        {m_result.SetWindowText("表达式不合法!");// 表达式不合法,判别出来并给出相应的错误提示

        }

        else

        {if(a.Sign)

              {m_result.SetWindowText("除数为零!");// 表达式不合法,可以判别出来并给出相应的错误提示

              }

              else

              {str.Format("%lf",a.GetV());

        m_result.SetWindowText(str);

              }

        }

}


以OnButton1()作为求值处理函数,函数的功能是单击等于(=)按钮,运算结果显示在IDC_EDIT2中

4.OnButton2()按钮的处理函数

双击“清除(C)”按钮,添加如下代码:

void CMyDlg::OnButton2()

{

       // TODO: Add your control notification handler code here

        m_result.SetWindowText("0");

     m_input.SetWindowText("");

     m_input.SetFocus();

}

// 函数的功能是把上次输入的表达式清空

5.OnButton3()按钮的处理函数

双击“全清(A)”按钮,添加如下代码:

void CMyDlg::OnButton3()

{

    // TODO: Add your control notification handler code here

       m_input.SetWindowText("");

        m_input.SetFocus();

    }

//函数的功能是把上次输入的表达式和运算结果都清除

6.OnTimer(UINT nIDEvent) 处理函数

CWnd::SetTimer(1,500,NULL);//设置时间每隔500ms更新一次。

void CMyDlg::OnTimer(UINT nIDEvent)

{

       // TODO: Add your message handler code here and/or call default

          CString ch[] = {"日","一","二","三","四","五","六"};

       SYSTEMTIME st;

       ::GetLocalTime(&st);

          CString str_temp;

          str_temp.Format("%u/%u/%u  星期"+ch[st.wDayOfWeek]+" %u:%u:%u\n",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);

          m_time.SetWindowText(str_temp);

       CDialog::OnTimer(nIDEvent);

}//函数的功能是把运算结果显示在IDC_EDIT3中

7.OnAbout()处理函数

void CMyDlg::OnAbout()

{

       // TODO: Add your command handler code here

       CAboutDlg about;

       about.DoModal();

}

//关于帮助和版权信息

8.OnQuit()处理函数

void CMyDlg::OnQuit()

{

       // TODO: Add your command handler code here

       OnOK();

}

//退出主程序菜单

9.全部代码如下:

// 计算器Dlg.cpp : implementation file

//

#include "stdafx.h"

#include "计算器.h"

#include "计算器Dlg.h"

#include "Calculate.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog

{

public:

    CAboutDlg();

// Dialog Data

    //{{AFX_DATA(CAboutDlg)

    enum { IDD = IDD_ABOUTBOX };

    //}}AFX_DATA

    // ClassWizard generated virtual function overrides

    //{{AFX_VIRTUAL(CAboutDlg)

    protected:

    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

    //}}AFX_VIRTUAL

// Implementation

protected:

    //{{AFX_MSG(CAboutDlg)

    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()

};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

    //{{AFX_DATA_INIT(CAboutDlg)

    //}}AFX_DATA_INIT

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

    CDialog::DoDataExchange(pDX);

    //{{AFX_DATA_MAP(CAboutDlg)

    //}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

    //{{AFX_MSG_MAP(CAboutDlg)

    //}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CMyDlg dialog

CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)

    : CDialog(CMyDlg::IDD, pParent)

{

    //{{AFX_DATA_INIT(CMyDlg)

        // NOTE: the ClassWizard will add member initialization here

    //}}AFX_DATA_INIT

    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32

    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}

void CMyDlg::DoDataExchange(CDataExchange* pDX)

{

    CDialog::DoDataExchange(pDX);

    //{{AFX_DATA_MAP(CMyDlg)

    DDX_Control(pDX, IDC_EDIT3, m_time);

    DDX_Control(pDX, IDC_EDIT2, m_result);

    DDX_Control(pDX, IDC_EDIT1, m_input);

    //}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CMyDlg, CDialog)

    //{{AFX_MSG_MAP(CMyDlg)

    ON_WM_SYSCOMMAND()

    ON_WM_PAINT()

    ON_WM_QUERYDRAGICON()

    ON_BN_CLICKED(IDC_BUTTON1, OnButton1)

    ON_BN_CLICKED(IDC_BUTTON2, OnButton2)

    ON_WM_TIMER()

    ON_BN_CLICKED(IDC_BUTTON3, OnButton3)

    ON_COMMAND(ID_ABOUT, OnAbout)

    ON_COMMAND(ID_QUIT, OnQuit)

    //}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CMyDlg message handlers

BOOL CMyDlg::OnInitDialog()

{

    CDialog::OnInitDialog();

    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.

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

        }

    }

    // Set the icon for this dialog.  The framework does this automatically

    //  when the application's main window is not a dialog

    SetIcon(m_hIcon, TRUE);         // Set big icon

    SetIcon(m_hIcon, FALSE);

    // Set small icon

    m_Mu.LoadMenu(IDR_MENU2);

    SetMenu(&m_Mu);

    CWnd::SetTimer(1,500,NULL);

    // TODO: Add extra initialization here

   

    return TRUE;  // return TRUE  unless you set the focus to a control

}

void CMyDlg::OnSysCommand(UINT nID, LPARAM lParam)

{

    if ((nID & 0xFFF0) == IDM_ABOUTBOX)

    {

        CAboutDlg dlgAbout;

        dlgAbout.DoModal();

    }

    else

    {

        CDialog::OnSysCommand(nID, lParam);

    }

}

// If you add a minimize button to your dialog, you will need the code below

//  to draw the icon.  For MFC applications using the document/view model,

//  this is automatically done for you by the framework.

void CMyDlg::OnPaint()

{

    if (IsIconic())

    {

        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle

        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;

        // Draw the icon

        dc.DrawIcon(x, y, m_hIcon);

    }

    else

    {

        CDialog::OnPaint();

    }

}

// The system calls this to obtain the cursor to display while the user drags

//  the minimized window.

HCURSOR CMyDlg::OnQueryDragIcon()

{

    return (HCURSOR) m_hIcon;

}

void CMyDlg::OnButton1()

{

    // TODO: Add your control notification handler code here

     CString str;

     char *ch;

     m_input.GetWindowText(str);

     ch = (LPSTR)(LPCTSTR)str;

     char ch2[50];

     strcpy(ch2,ch);

     Cal a(ch2);

     if(!a.OK)

     {

     m_result.SetWindowText("表达式不合法!");

     }

     else

     {

        if(a.Sign)

        {

        m_result.SetWindowText("除数为零!");

        }

        else

        {

             str.Format("%lf",a.GetV());

     m_result.SetWindowText(str);

        }

     }

}

void CMyDlg::OnTimer(UINT nIDEvent)

{

    // TODO: Add your message handler code here and/or call default

       CString ch[] = {"日","一","二","三","四","五","六"};

       SYSTEMTIME st;

       ::GetLocalTime(&st);

       CString str_temp;

       str_temp.Format("%u/%u/%u  星期"+ch[st.wDayOfWeek]+" %u:%u:%u\n",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);

       m_time.SetWindowText(str_temp);

   

    CDialog::OnTimer(nIDEvent);

}

void CMyDlg::OnButton2()

{

    // TODO: Add your control notification handler code here

     m_result.SetWindowText("0");

     m_input.SetWindowText("");

     m_input.SetFocus();

void CMyDlg::OnButton3()

{

    // TODO: Add your control notification handler code here

       m_input.SetWindowText("");

        m_input.SetFocus();

   

}

void CMyDlg::OnAbout()

{

    // TODO: Add your command handler code here

    CAboutDlg about;

    about.DoModal();

   

}

void CMyDlg::OnQuit()

{

    // TODO: Add your command handler code here

    OnOK();

}

三.总结:

    在设计当中我认识到开发一项好的软件不是某一个人就能完成的任务。一个团队的小组,一个勤奋的小组非常重要,沟通是解决问题的就好办法。俗话也说得好:“不怕虎一样的敌人,就怕猪一样的队伍”。所以小组中的每个成员的能力与协作能力也是致关重要的。同时,不仅是团队内部的交流,更多需要协调好团队之间的交流。

    其次呢,在设计过程中我了解了,在开发一个项目时一定要先做好规划,按照软件的开发过程,详细地写好每一个必要的文档。一般的规则是,写文档需要团队协作,这样就允许开发人员和文档编写者利用彼此的长处,取长补短。例如,如果预期读者是系统设计师,开发人员需要提供技术细节,然后文档编写者按照正确语法组织和编辑内容。软件文档的最主要目标是传达一个系统的技术要素和使用方法。第二个目标是提供软件开发过程中的需求,决策,行为,角色和责任的书面记录。只有实现了这两个目标,软件文档才真正提供了有意义的信息。软件的概念就是:程序+文档,程序就是文档,文档集成在程序中。它要求在选择开发环境时不仅要考虑环境对设计、开发的完美支持,而且要考虑对维护、文档的支持;它要求软件人员在设计、开发过程中要考虑维护问题、文档问题;它要求程序与文档存储在同一位置、同一系统中;它要求使用相同工具进行程序与文档的书写、检索;它要求在编写和维护程序的同时形成文档,在书写文档时编写、维护程序。程序与文档合一的概念不仅存在于系统的设计、开发阶段而且存在于系统的维护阶段,它贯穿软件的生命周期。

本次MFC简易表达式计算器的制作,学习到了MFC基本的编程方法,增加了小组开发的团结协作能力。对C++的OOP编程思想理解进一步加深。但是程序仍然存在一定的问题,比如除数不能为0的Exception handle,符号键多次点击结果混乱,输入的字符除了数字还有其他不合法的字符(如字母、空格和其它标点符号等)。由于时间仓促,如果有更多的时间,这些问题必定会迎刃而解。通过这次课程设计,可以很好的加深对C++的理解,以后对Windows 应用程序的开发势必会轻车熟路。

四、附录

1.Calculate.cpp源代码

#ifndef CALCULATE_H

#define CALCULATE_H

#include<String.h>

class Cal

{

public:

   struct Tree

   {

      char ch[50];

      Tree* Lchild;

      Tree* Rchild;

   };

public:

   int Sign;

   bool OK;

public:

     Cal(char* Ex);

     bool Judge(char* Ex);

     void GetTree(char* Ex, Tree* Node);

     double GetResult(Tree* Node);

     int GetFig(char ch);

     void Getstring(char* Ex, int s, char* ch);

     double GetValue(char* ch);

     double GetV();

     void Drop(Tree *Node);

     ~Cal();

private:

    Tree *Node;

    double Result;

};

Cal::Cal(char* str)

{

   Sign = 0;

   OK = true;

   char Ex[50];

   strcpy(Ex,str);

   if(Judge(Ex))

   {

      Node = new Tree;

      GetTree(Ex,Node);

      Result = GetResult(Node);

   }

   else

       OK = false;

}

Cal::~Cal()

{

    if(OK)

    Drop(Node);

#ifdef MYDEBUG

    cout<<"end"<<endl;

#endif

}

void Cal::GetTree(char* Ex, Tree* Node)

{

    int length = strlen(Ex);

    int tag = length;

    char Bch[50];

    

    int i;

#ifdef MYDEBUG

    cout<<"             Ex:  "<<Ex<<endl;

#endif

    if(Ex[length-1]==')')

    { 

        int acout = -1;

       for(i=length-2;i>=0;i--)

       {

           if(Ex[i]==')')

               acout--;

           if(Ex[i]=='(')

           {

              acout++;

              if(acout==0)

              {

                  tag = i;

                  break;

              }

           }

       }

       if(i < 0)

       {

           Sign = 1;

           return ;

       }

       if(tag==0)

       {

           Ex[length-1]='\0';

          Getstring(Ex,1,Bch);

          GetTree(Bch,Node);

       }

       if(tag!=0)

       {

          int l_tag = tag;

          int t = 0;

          for(int j = tag - 1; j >= 0; j--)

          {          

              if(Ex[j] == ')')

                  t--;

              if(Ex[j] == '(')

                  t++;

              if(Ex[j]=='+'||Ex[j]=='-'||Ex[j]=='*'||Ex[j]=='/'&&t==0)

              {

                    l_tag = j;

                  if(Ex[j]=='+'||Ex[j]=='-')

                      break;

              }

          }

          if(t==0)

           {

              Getstring(Ex,l_tag+1,Bch);

              Tree *Rchild = new Tree;

              Tree *Lchild = new Tree;

              Node->Lchild = Lchild;

              Node->Rchild = Rchild;

              GetTree(Bch,Node->Rchild);

               *(Node->ch) = Ex[l_tag];

               *(Node->ch+1) = '\0';

               Ex[l_tag] = '\0';

               GetTree(Ex,Node->Lchild);

           }

          else

          {

             Sign = 1;   

              return ;

          }

       }

    }

    else

    {

        int t = 0;

        for(i=length-1;i>=0;i--)

        {

            if(Ex[i]==')')

                t++;

            if(Ex[i]=='(')

                t--;

            if(Ex[i]=='+'||Ex[i]=='-'||Ex[i]=='*'||Ex[i]=='/'&&t==0)

              if(tag==length)

              {   

                   tag=i;

                  if(Ex[tag]=='+'||Ex[tag]=='-'&&t==0)

                  { 

                      Tree *Rchild = new Tree;

                      Tree *Lchild = new Tree;

                      Node->Lchild = Lchild;

                      Node->Rchild = Rchild;

                      Getstring(Ex,tag+1,Bch);

                      strcpy(Node->Rchild->ch,Bch);

                      Node->Rchild->Lchild=NULL;

                      Node->Rchild->Rchild=NULL;

                      *(Node->ch) = Ex[tag];

                      *(Node->ch+1) = '\0';

                      Ex[tag]='\0';

                      GetTree(Ex,Node->Lchild);

                       break;

                  }

              }

              if(tag!=length&&(Ex[i]=='+'||Ex[i]=='-')&&t==0)

              {

                  tag = i;

                  Tree *Rchild = new Tree;

                  Tree *Lchild = new Tree;

                  Node->Lchild = Lchild;

                  Node->Rchild = Rchild;

                  *(Node->ch)=Ex[tag];

                  *(Node->ch+1) = '\0';

                  Getstring(Ex,tag+1,Bch);

                  GetTree(Bch,Node->Rchild);

                  Ex[tag]='\0';

                  GetTree(Ex,Node->Lchild);

                      break;

              }

        }

        if(i<0 &&tag!=length)

        {

             Tree *Rchild = new Tree;

             Tree *Lchild = new Tree;

             Node->Lchild = Lchild;

             Node->Rchild = Rchild;

             Getstring(Ex,tag+1,Bch);

             strcpy(Node->Rchild->ch,Bch);

             Node->Rchild->Lchild=NULL;

             Node->Rchild->Rchild=NULL;

             *(Node->ch) = Ex[tag];

             *(Node->ch+1) = '\0';

             Ex[tag]='\0';

             GetTree(Ex,Node->Lchild);

        }

        if(i<0 &&tag==length)

        {

            strcpy(Node->ch ,Ex);

            Node->Lchild=NULL;

            Node->Rchild=NULL;

        }

    }

}

double Cal::GetResult(Tree* Node)

{

   if(Node->Lchild!=NULL&&Node->Rchild!=NULL)

   {

      switch(*(Node->ch))

      {

         case '+': return GetResult(Node->Lchild) + GetResult(Node->Rchild);

         case '-': return GetResult(Node->Lchild) - GetResult(Node->Rchild);

         case '*': return GetResult(Node->Lchild) * GetResult(Node->Rchild);

         case '/':

             if(GetResult(Node->Rchild) == 0)

             {  

                 Sign = 1;

                 return -1;

             }

             else

             return GetResult(Node->Lchild) / GetResult(Node->Rchild);

      }

   }

   else

   {

       double Value = GetValue(Node->ch);

      // delete Node;

       return Value;

      

   }

      

}

bool Cal::Judge(char* Ex)

{

    int len = strlen(Ex);

    int t=0;

    if(len == 1 )

        if(Ex[0] == '+'||Ex[0] == '-'||Ex[0] == '*'||Ex[0] == '/')

            return false;

    for(int i =1; i < len; i++)

    {

       if((Ex[i-1] == '+'||Ex[i-1] == '-'||Ex[i-1] == '*'||Ex[i-1] == '/')

           &&(Ex[i] == '+'||Ex[i] == '-'||Ex[i] == '*'||Ex[i] == '/'))

           return false;

    }

    for(i = 0; i < len; i++)

    {

       if(Ex[i]==')')

           t++;

       if(Ex[i]=='(')

           t--;

    }

    if(t!=0)

        return false;

    for(i=0;i<len;i++)

    {

       if(Ex[i]!='0'&&Ex[i]!='1'&&Ex[i]!='2'&&Ex[i]!='3'&&Ex[i]!='4'&&Ex[i]!='5'&&Ex[i]!='6'

           &&Ex[i]!='7'&&Ex[i]!='8'&&Ex[i]!='9'&&Ex[i]!='('&&Ex[i]!=')'&&Ex[i]!='+'&&Ex[i]!='-'

           &&Ex[i]!='*'&&Ex[i]!='/'&&Ex[i]!='\n'&&Ex[i]!='.')

           return false;

    }

    return true;

}

void Cal::Getstring(char* Ex, int s, char* ch)

{

   for(int i=s,j=0;i < strlen(Ex);i++,j++)

       *(ch+j)=Ex[i];

   ch[j]='\0';

}

double Cal::GetValue(char* ch)

{

    int tag = 0;

    double Value = 0;

    double n = 1;

   for(int i=0;i<strlen(ch);i++)

   {

       if(ch[i]=='.')

         tag = 1;

       else

       {

          if(tag == 0)

              Value = Value*10+GetFig(ch[i]);

          if(tag == 1)

          {

             n = n/10;

             Value = Value + ((double)GetFig(ch[i])*n);

          }

       }

   }

   return Value;

}

int Cal::GetFig(char ch)

{

  if(ch=='0')

      return 0;

  if(ch=='1')

      return 1;

  if(ch=='2')

      return 2;

  if(ch=='3')

      return 3;

  if(ch=='4')

      return 4;

  if(ch=='5')

      return 5;

  if(ch=='6')

      return 6;

  if(ch=='7')

      return 7;

  if(ch=='8')

      return 8;

  if(ch=='9')

      return 9;

  return 0;

}

double Cal::GetV()

{

   return Result;

}

void Cal::Drop(Tree* Node)

{

    if(Node->Lchild!=NULL)

    {

        Drop(Node->Lchild);

        Drop(Node->Rchild);

        delete Node;

    }

    else

        delete Node;

}

#endif

更多相关推荐:
计算器设计的java课程设计报告

华东交通大学课程设计华东交通大学课程设计课程设计题目计算器设计课程题目年级专业学号姓名组员指导教师Java程序设计信息一班1华东交通大学课程设计课程设计论文任务书基础学院信息与计算科学专业20xx1班一课程设计...

计算机综合课程设计报告

计算机综合课程设计报告小组编号06课题名称趣味贪吃蛇小组成员20xx年10月计算机综合课程设计报告目录目录11项目背景112系统目标121系统功能分析2211功能12212功能2222系统性能指标223系统平台...

MFC计算器课程设计报告

MFC计算器课程设计报告计算机应用3班黄锦湫罗洁饶益指导老师蒋鹏20xx315一题目利用MFC框架编写简易计算器要求使用MFC框架在VisualStudio60环境下编写一个简易的计算器支持任意位数的加减乘数正...

计算机网络课程设计报告

计算机网络课程设计报告一.课程设计的题目、目的及要求.........................................................2二.课程设计的内容(分析和设计).....…

C++简单计算器课程设计报告

武汉理工大学专业课程设计2课程设计说明书目录1基本功能描述12设计思路13软件设计431设计步骤44结论与心得体会127附设计中的关键源代码1472测试结果15简单计算器1基本功能描述简单计算器包括双目运算和单...

Java课程设计报告-计算器

Java课程设计报告计算器第一部分设计的内容要求11Windows自带计算器版面设计12计算器计算功能算法实现第二部分设计思想21根据图形用户界面设计方法设计计算器版面容器类窗口Window类面板Panel类框...

课程设计报告——计算器

北京化工大学20xx20xx课程设计报告计算机科学与技术计算器程序的设计与实现数据结构课程设计班级计科1001北京化工大学信息科学与技术学院计算机科学与技术专业北京化工大学20xx20xx课程设计报告计算机科学...

李晓奇 丁健华 吴继超等MFC计算器课程设计报告

MFC表达式计算器课程设计报告班级5班学生姓名及学号丁健华020xx507李晓奇020xx513吴继超020xx516完成日期20xx年10月13日小组成员及分工李晓奇主要负责Calculatecpp代码的编写...

计算器实验报告

目录一系统开发的背景1二系统分析与设计1一二计算器的主要功能1系统模块结构设计1三系统的设计与实现2一二计算器的初始界面2一般计算3三解一元二次方程5四计算银行本利和5四系统测试7一二测试主函数MAIN7测试一...

VB计算器课程设计报告

石家庄铁道学院课程设计计算器单位工程力学系专业工程力学学号20xx2719学生姓名孙亚光指导教师王学军完成日期20xx年8月30日摘要计算器程序的主要功能是相应鼠标事件相应鼠标事件就是当用户想要进行运算时可以用...

简单计算器C语言课程设计报告书

C语言课程设计报告书题目:简单计算器院系:班级:学号:姓名:一、课程设计目的1.巩固和加深C语言课程的基本知识的理解和掌握2.掌握C语言编程和程序调试的基本技能3.利用C语言进行基本的软件设计4.掌握书写程序设…

C++简单计算器课程设计报告

武汉理工大学专业课程设计2课程设计说明书目录1基本功能描述12设计思路13软件设计431设计步骤432界面设计533关键功能的实现114结论与心得体会125参考文献136思考题137附录1471调试报告1472...

计算器课程设计报告(34篇)