【课程设计|C++】C++程序设计基础:计算器(MFC)

海轰Pro

共 18474字,需浏览 37分钟

 ·

2021-08-18 19:17

1.设计目的和内容

1.1.设计目的

  • 学习Visual C++的MFC开发程序的步骤。
  • 综合运用所学的类、继承和多态的知识。
  • 进一步掌握程序的调试方法。

1.2.设计内容

  • 利用MFC的向导,创建基于单文档的应用程序;
  • 实现简单的四则运算
  • 进行科学运算,如log、tan、sin
  • 多项式运算

2.基本功能描述

2.1.工程的新建

打开Microsoft Visual C++ 6.0

点击File —> New

在Projects中选择 MFC AppWizard (exe) ;

在 Project name中输入工程的名字Graphic,在 Location中选择工程存放的路径,填完后点击OK按钮。

图1工程创建过程

(如图1)填完后点击OK按钮,弹出对话框(如图2)。

弹出来的对话框中我们可以选择生成三种不同类型的应用程序

  • 单文档
  • 多文档
  • 对话框。

单文档程序如记事本,在一个应用程序中只能对一个文档进行操作,降低了编程的复杂度并减少了运行程序时所需的资源。对某些小型应用(比如文本编辑器或小型图像编辑器)可以采用这种类型的窗口应用程序。

在这个程序中,我们就需要单文档,选择完后点击Next,设置默认,最后点击Finish,

完成工程的创建。

2.2.单对话框简介

生成单文档程序后,进行编译

再运行,我们可以看到以下的结果。

图3编译界面

2.3 界面布局

利用MFC自带的按钮、编辑框等组件,设计出计算器的初始界面。

3.设计思路

计算器的整个思想就是通过图形化界面,获取用户进行的操作和输入的数据,并按照要求进行相应的数字逻辑运算。

设计的要素就是通过按下不同的按钮,程序可以获取不同的数值,同时判断数的位置,最后通过确定键的确认,在屏幕上输出答案。

设计的难点有几个。

第一,数值的确定与传统方法不一样,比如,我们在计算器中输入123,按下的键依次是1,2,3.而每次读出的数据也是相应的单数字。

为此获取到的数字为123,我们必须设计一个算法,即每次输入数之前,先用前一次的数(第一次的数为0)乘以10,加上刚刚按下的数。

在按下符号键或复位键时,flag变换,标记是否数字输入完毕。同时符号键的设计也就是简单的为一个符号变量赋值,因为程序是固定的进行两个数的运算,只是中间的符号不同。

在这里有点区别的是,常规符号如此,科学运算符号并不如此。一般的科学运算数只有一位,所以在进行科学运算的时候,需要特别标记。

多项式运算采用的是中缀算法,也就是先对输入的多项式进行中缀变换,然后利用中缀优先级法则进行运算。这里是整个计算器设计的难点。

4.软件设计

4.1.设计步骤及关键代码

①所需变量的定义与声明

m_display2 = 0.0;
num1 = 0;
num2 = 0;
result = 0.0;
str = "";
str_flag = FALSE;
continue_flg = FALSE;
downDot = FALSE;
count = 1;

//{{AFX_DATA_INIT(CMyDlg)
m_display = _T("");
m_display1 = 0.0;
m_display2 = 0.0;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

②判断数值是否结束

double CMyDlg::buttonDownNum(int numSize)
{
    if (!str_flag) //运算符没有被按下,那就是num1
    {
        if (!continue_flg) //按下一次
        {
            num1 = numSize;
            continue_flg = TRUE;
        }
        else
        {
            num1 = num1 * pow(10, count) + numSize;
            if (downDot)
            {
                num1 = num1 / (pow(10, count));
                count++;
            }
        }

        return num1;
    }
    else //有运算符被按下
    {
        if (!continue_flg) //是否连续按下
        {
            num2 = numSize;
            continue_flg = TRUE;
        }
        else
        {
            num2 = num2 * pow(10, count) + numSize;
            if (downDot)
            {
                num2 = num2 / (pow(10, count));
                count++;
            }
        }

        return num2;
    }
}

③优先级判断

void CMyDlg::OnButton1()
{
    UpdateData(true);
    CString aa = m_display;

    Stack<int> number;     //数字栈
    Stack<char> character; //运算符栈
    character.Push('=');
    // CString aa="1+(1*2)+2#";
    int numaa = strlen(aa);
    int kk = 0;

    //cout<<numaa;
    int ch = aa[kk++];
    // int ch = getchar();
    //它从标准输入里读取下一个字符。返回类型为int型,返回值为用户输入的ASCⅡ码,出错返回-1,比如输入a ,返回97,输入3,返回51
    char b;
    b = static_cast<char>(ch); //b是ch转换的字符
    while (b != '=' || character.getTop() != '=')
    {
        if (ch > 48 && ch <= 57)
        { //这里非常容易写错啊!不是ch>0 && ch<=9,或者b>0 && b<=9;
            number.Push(ch - 48);
            ch = aa[kk++]; // getchar();
            b = static_cast<char>(ch);
        }
        else
        {
            switch (Priority(character.getTop(), b))
            {
            case '<'//栈顶元素优先级低
                character.Push(b);
                ch = aa[kk++]; //getchar();
                b = static_cast<char>(ch);
                break;
            case '='//脱一个'('括号 并且接收下一个字符
                character.Pop();
                ch = aa[kk++]; //getchar();
                b = static_cast<char>(ch);
                break;
            case '>'//出栈并且把运算结果入栈
                number.Push(Compute(number.Pop(), number.Pop(), character.Pop()));
                /*int result=number.Pop()+number.Pop();
    cout<<result;
    number.Push(result);*/

                break;
            }
        }
    }
    // cout<<"运算结果是"<<"   "<<number.getTop()<<'\n';
    // cout<<"运算结果是:"<<number.getTop()<<endl;
    //printf("运算结果是 %d \n",number.getTop());
    // CString bb=CString.Format(_T("%d"),2);
    m_display1 = number.getTop();
    UpdateData(false);

    //return 0;
}

④优先级设计

char CMyDlg::Priority(char ch1, char ch2)
{
    int a;
    int b;
    switch (ch1)
    {
    case '#':
        a = 0;
        break;
    case '(':
        a = 1;
        break;
    case '+':
        a = 3;
        break;
    case '-':
        a = 3;
        break;
    case '*':
        a = 5;
        break;
    case '/':
        a = 5;
        break;
    case '%':
        a = 5;
        break;
    case '^':
        a = 7;
        break;
    case ')':
        a = 8;
        break;
    }
    switch (ch2)
    {
    case '#':
        b = 0;
        break;
    case '(':
        b = 8;
        break;
    case '+':
        b = 2;
        break;
    case '-':
        b = 2;
        break;
    case '*':
        b = 4;
        break;
    case '/':
        b = 4;
        break;
    case '%':
        b = 4;
        break;
    case '^':
        b = 6;
        break;
    case ')':
        b = 1;
        break;
    }
    if (a < b)
        return '<';
    else if (a == b)
        return '=';
    else
        return '>';
}

⑤多项式结果运算

int CMyDlg::Compute(int a, int b, char sign)
{
    int result;
    switch (sign)
    {
    case '+':
        result = a + b;
        break;
    case '-':
        result = a - b;
        break;
    case '*':
        result = a * b;
        break;
    case '/':
        result = a / b;
        break;
    case '%':
        result = a % b;
        break;
    case '^':
        result = a ^ b;
        break;
    }
    return result;
    // TODO: Add your control notification handler code here
}

⑥常规按钮

void CMyDlg::OnButton2()
{
    m_display2 = buttonDownNum(1);
    UpdateData(false);
    // TODO: Add your control notification handler code here
}

void CMyDlg::OnButton3()
{
    m_display2 = buttonDownNum(2);
    UpdateData(false);
}

void CMyDlg::OnButton4()
{
    m_display2 = buttonDownNum(3);
    UpdateData(false);
}

void CMyDlg::OnButton5()
{
    m_display2 = buttonDownNum(4);
    UpdateData(false);
}

void CMyDlg::OnButton6()
{
    m_display2 = buttonDownNum(5);
    UpdateData(false);
}

void CMyDlg::OnButton7()
{
    m_display2 = buttonDownNum(6);
    UpdateData(false);
}

void CMyDlg::OnButton8()
{
    m_display2 = buttonDownNum(7);
    UpdateData(false);
}

void CMyDlg::OnButton9()
{
    m_display2 = buttonDownNum(8);
    UpdateData(false);
}

void CMyDlg::OnButton10()
{
    m_display2 = buttonDownNum(9);
    UpdateData(false);
}

void CMyDlg::OnButton11()
{
    m_display2 = buttonDownNum(0);
    UpdateData(false);
}

void CMyDlg::OnButton13()
{
    str = "+";
    str_flag = TRUE;
    continue_flg = FALSE;
    downDot = FALSE;
    count = 1;
    UpdateData(FALSE);
}

⑦运算法则定义

void CMyDlg::OnButton16()
{
    if (str == "+")
        result = num1 + num2;
    else if (str == "-")
        result = num1 - num2;
    else if (str == "*")
        result = num1 * num2;
    else if (str == "/")
    {
        result = double(num1) / double(num2);
    }
    else if (str == '^')
        result = pow(num1, num2);
    else if (str == 'k')
        result = pow(num1, 1.0 / num2);
    else if (str == 's')
        result = sin(num2 * 3.1415926 / 180);
    else if (str == 'c')
        result = cos(num2 * 3.1415926 / 180);
    else if (str == 't')
        result = tan(num2 * 3.1415926 / 180);
    else if (str == 'l')
        result = log(num2);
    else if (str == 'e')
        result = exp(num2);
    num1 = result;
    m_display2 = result;
    str_flag = FALSE;
    continue_flg = FALSE;
    downDot = FALSE;
    count = 1;

    UpdateData(FALSE);
}

编写其函数:

pCmdUI->SetCheck(shape==1); //显示 图标的样式

⑧颜色板的调用

CColorDialog Color; //定义画框
if (Color.DoModal() == IDOK)
{
    m_ncolor = Color.GetColor();
}

4.2.界面设计

5.结论与心得体会

通过这次的课设,自己学到了很多,比如团队之间的合作,还有一些自己以前不是很了解的知识。

通过团队合作,可以得到很多不一样的思路,不一样的算法,每个人的思维是不一样的,所以,我们应该要吸取不同人的优点,吸收理解成自己的优点。

在这次合作的过程中,产生了很多的好点子,尽管最后有很多的功能没有实现,毕竟自己的技术还是不行,但是,有一些很好的想法也是不错了,可以锻炼我们的思维。

在这次的课设题目中,充分的将自己平时所学应用到实践中,比如栈还有java html css js等一些新语言,在这次的课设中,虽然很累,但是也还是很值得的,从刚开始的一头雾水,通过查阅资料和在老师的指导下,慢慢的懂了,慢慢的理解了其本质。希望在今后的日子里,自己的编程能力会越来越强,可以写出自己满意的代码!

6.参考文献

  • PDF:Windows编程基础andMFC
  • PDF:MFC入门
  • PDF:深入浅出MFC

项目源码

下载路径:

工程文件下载

结语

代码均为原创

版权归原作者所有

「仅供小伙伴们学习参考使用」

请勿用作其余用途!

创作不易

如果您觉得写的不错的话

「点赞+在看+收藏」 ❤️

写留言

浏览 72
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报