用 C++ 创建控制台计算器

C++ 程序员通常从在命令行上运行的“Hello, world!”应用程序开始。 你将以本文为起点,逐步进阶,加深学习难度:计算器应用。

先决条件

  • 在 Visual Studio 中安装“使用 C++ 的桌面开发”工作负载并在计算机上运行。 请参阅在 Visual Studio 中安装 C++ 支持,了解如何安装该工作负载。
  • 本教程演示了“编辑并继续”这项功能,使用此功能,可以在应用运行时对代码进行更改。 若要启用“编辑并继续”,请在主菜单中选择“工具”>“选项”>“调试”>“常规”,并确保选中“要求源文件与原始版本完全匹配”。

创建应用项目

Visual Studio 使用项目来组织应用的代码,使用解决方案来组织一个或多个项目。 项目包含用于生成应用的所有选项、配置和规则。 它还负责管理所有项目文件和任何外部文件间的关系。 若要创建应用,先创建一个新项目和解决方案。

  1. 启动 Visual Studio - 将出现 Visual Studio 启动对话框。 选择“创建新项目”以开始使用。

    Visual Studio 2022 启动时出现的对话框的屏幕截图。

    该对话框包含这些选项:克隆存储库、打开项目或解决方案、打开本地文件夹和新建项目。

  2. 在项目模板列表中,依次选择“控制台应用”、“下一步”。

    Visual Studio“新建项目”对话框的屏幕截图。已突出显示“控制台应用”模板选项。

    重要

    请确保选择 Console App 模板的 C++ 版本。 它具有 C++、Windows 和 Console 标记,该图标在角落处有“++” 。

  3. 在“配置新项目”文本框中,选择“项目名称”文本框,将新项目命名为 CalculatorTutorial,然后选择“创建”

    Visual Studio“配置新项目”对话框的屏幕截图。其中包含这些字段:项目名称、项目位置和解决方案名称。

    将创建一个空的 C++ Windows 控制台应用程序“Hello World”应用。 控制台应用程序使用 Windows 控制台窗口显示输出并接受用户输入。 在 Visual Studio 中,将打开一个编辑器窗口并显示生成的代码:

    // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //
    
    #include <iostream>
    
    int main()
    {
        std::cout << "Hello World!\n";
    }
    
    // Run program: Ctrl + F5 or Debug > Start Without Debugging menu
    // Debug program: F5 or Debug > Start Debugging menu
    
    // Tips for Getting Started:
    //   1. Use the Solution Explorer window to add/manage files
    //   2. Use the Team Explorer window to connect to source control
    //   3. Use the Output window to see build output and other messages
    //   4. Use the Error List window to view errors
    //   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
    //   6. In the future, to open this project again, go to File > Open > Project and select the .sln file
    

验证新应用是否生成并运行

新的 Windows 控制台应用程序模板创建了一个简单的 C++“Hello World”应用。 此时,可以看到 Visual Studio 如何生成并运行直接从 IDE 创建的应用。

  1. 若要生成项目,请从“生成”菜单选择“生成解决方案”。 “输出”窗口将显示生成过程的结果 。

    Visual Studio 输出窗口的屏幕截图。显示了生成成功的消息。

  2. 若要运行代码,请在菜单栏上依次选择“调试”、“开始执行(不调试)”(Ctrl+F5)。

    Visual Studio 调试控制台的屏幕截图,其中显示了应用程序的输出:Hello World!。

    随即将打开控制台窗口,然后运行你的应用。

    在 Visual Studio 中启动控制台应用时,它会运行代码,然后输出“按任意键关闭此窗口。 。 .”,让你有机会看到输出。

    祝贺你! 你在 Visual Studio 中创建了首个“Hello, world!”控制台应用!

  3. 按任意键关闭该控制台窗口并返回到 Visual Studio。

现在即可使用你的工具在每次更改后生成并运行应用,以验证代码是否仍按预期运行。 如果未按预期运行,稍后我们将向你演示调试方法。

编辑代码

现在,将此模板中的代码修改为计算器应用。

  1. CalculatorTutorial.cpp 文件的内容替换为以下代码,使其与本示例一致:

    // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //
    
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        cout << "Calculator Console Application" << endl << endl;
        cout << "Please enter the operation to perform. Format: a+b | a-b | a*b | a/b"
            << endl;
        return 0;
    }
    
    // Run program: Ctrl + F5 or Debug > Start Without Debugging menu
    // Debug program: F5 or Debug > Start Debugging menu
    // Tips for Getting Started:
    //   1. Use the Solution Explorer window to add/manage files
    //   2. Use the Team Explorer window to connect to source control
    //   3. Use the Output window to see build output and other messages
    //   4. Use the Error List window to view errors
    //   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
    //   6. In the future, to open this project again, go to File > Open > Project and select the .sln file
    

    了解代码:

    • #include 语句允许引用位于其他文件中的代码。 有时,文件名使用尖括号 (<>) 括起来;其他情况下,使用引号 (" ") 括起来。 通常,引用 C++ 标准库时使用尖括号,引用其他文件时使用引号。
    • using namespace std; 行提示编译器期望在此文件中使用 C++ 标准库中的内容。 如果没有这一行,库中的每个关键字都必须以 std:: 开头,以表示其范围。 例如,如果没有该行,则对 cout 的每个引用都必须写为 std::coutusing 语句的使用是为了使代码看起来更干净。
    • cout 关键字用于在 C++ 中打印到标准输出。 << 运算符提示编译器将其右侧的任何内容发送到标准输出。
    • endl 关键字与 Enter 键类似;用于结束该行并将光标移动到下一行。 如果要执行相同的操作,最好在字符串中使用 \n(用 "" 包含),因为使用 endl 会始终刷新缓冲,进而可能影响程序的性能。 但是,由于这是一个非常小的应用,所以改为使用 endl 以提高可读性。
    • 所有 C++ 语句都必须以分号结尾,所有 C++ 应用程序都必须包含 main() 函数。 该函数是程序开始运行时运行的函数。 若要使用所有代码,必须可从 main() 访问所有代码。
  2. 要保存文件,请按下 Ctrl+S,或者选择 IDE 顶部附近的“保存”图标,即菜单栏下工具栏中的软盘图标

  3. 要运行该应用程序,请按“Ctrl+F5”或转到“调试”菜单,然后选择“启动但不调试”。 应会显示一个控制台窗口,其中显示代码中指定的文本。

  4. 完成后,请关闭控制台窗口。

添加代码来执行一些数学运算

类就像执行某事的对象的蓝图。 在这种情况下,我们将定义一个计算器类来包含数学逻辑。

添加 Calculator 类

  1. 转到“项目”菜单,然后选择“添加类”。 在“类名”编辑框中,输入“Calculator” 。 选择“确定”

    Visual Studio“添加类”对话框的屏幕截图。

    类名字段设置为 Calculator。 .h 文件字段设为 Calculator.h。 .cpp 文件字段设为 Calculator.cpp。 基类字段为空。 其他选项(虚拟析构函数、内联函数和非托管函数)均未选中。

    这会向项目中添加两个新文件。 若要同时保存所有已更改的文件,请按“Ctrl+Shift+S” 。 这是“文件”>“全部保存”的键盘快捷方式 。 在“保存”按钮旁边还有一个用于“全部保存”的工具栏按钮,这是两个软盘的图标 。 一般来说,最好经常使用“全部保存”,这样你保存时就不会遗漏任何文件 。

    “添加类”向导创建与该类同名的 .h.cpp 文件。 可以在 IDE 一侧的“解决方案资源管理器”窗口中看到项目文件的完整列表 。 如果该窗口不可见,则可从菜单栏中打开它:选择“查看”>“解决方案资源管理器”

    Visual Studio 解决方案资源管理器窗口的屏幕截图。

    计算器教程 (Calculator Tutorial) 项目具有包含 Calculator.h 的头文件节点。 源文件节点包含 Calculator.cpp 和 CalculatorTutorial.cpp。 引用、外部依赖项和资源文件的节点可见,但处于关闭状态。

    可通过在“解决方案资源管理器”窗口中双击文件将其打开。 双击 Calculator.h 将其打开。

  2. Calculator.h 的内容替换为以下代码,使文件现在如下所示:

    #pragma once
    class Calculator
    {
    public:
        double Calculate(double x, char oper, double y);
    };
    

    了解代码

    • 此代码声明了一个名为 Calculate 的新函数,我们将使用它来运行加法、减法、乘法和除法的数学运算。
    • C ++ 代码被组织成标头 (.h) (.h) 文件和源 (.cpp) 文件。 所有类型的编译器都支持其他几个文件扩展名,但这些是要了解的主要文件扩展名。 函数和变量通常在头文件中进行声明(即在头文件中指定名称和类型)和实现(或在源文件中指定定义) 。 若要访问在另一个文件中定义的代码,可以使用 #include "filename.h",其中 filename.h 是声明要使用的变量或函数的文件的名称。
    • 最好根据代码的功能将代码组织到不同的文件中,方便稍后需要这些代码时能够轻易查找到。 在本例中,我们分别定义了 Calculator 类和包含 main() 函数的文件,但我们计划在 main() 中引用 Calculator 类。
  3. Calculate 下方会出现绿色波浪线,因为尽管已声明 Calculate 函数,但并未定义该函数。 将鼠标悬停在 Calculate 上,单击显示的螺丝刀上的向下箭头,然后选择“在 Calculator.cpp 中创建 "Calculate" 定义”。

    Visual Studio 编辑器窗口中螺丝刀图标下拉列表的屏幕截图。突出显示了“在 Calculator.cpp 中创建计算定义”选项。

    此代码将添加到 Calculator.cpp

    Visual Studio 编辑器的屏幕截图,其中显示“Calculate”构造函数的定义。

    将构造函数定义为:double Calculator::Calculate( double x, char oper, double y) { return 0.0; }

    目前,它只返回 0.0。 让我们来更改它。

  4. 切换到编辑器窗口中的 Calculator.cpp 文件。 将 Calculator::Calculate(double x, char oper, double y) 的内容替换为:

    double Calculator::Calculate(double x, char oper, double y)
    {
        switch(oper)
        {
            case '+':
                return x + y;
            case '-':
                return x - y;
            case '*':
                return x * y;
            case '/':
                return x / y;
            default:
                return 0.0;
        }
    }
    

    了解代码

    • 函数 Calculate 使用数字、运算符和第二个数字,然后对数字执行请求的操作。
    • Switch 语句检查提供了哪个运算符,并仅执行与该操作对应的情况。 “default: case”是一个回滚,以防用户键入一个不被接受的运算符,因此程序不会中断。 通常,最好以更简洁的方式处理无效的用户输入,但这超出了本教程的范围。
    • double 关键字表示支持小数的数字类型。 因此,Calculator 可以处理十进制数学和整数数学。 要始终返回这样的数字,需要 Calculate 函数,因为代码的最开始是 double(这表示函数的返回类型),这就是为什么我们在默认情况下返回 0.0。
    • .h 文件声明函数“prototype”,它预先告诉编译器它需要什么参数,以及期望它返回什么样的返回类型。 .cpp 文件包含该函数的所有实现细节。

如果此时再次生成并运行代码,则在询问要执行的操作后,它会立即退出。 因此,修改 main 函数以执行多个计算。

调用 Calculator 类的成员函数

  1. 按如下所示更新 CalculatorTutorial.cpp 中的 main 函数:

    // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //
    
    #include <iostream>
    #include "Calculator.h"
    
    using namespace std;
    
    int main()
    {
        double x = 0.0;
        double y = 0.0;
        double result = 0.0;
        char oper = '+';
    
        cout << "Calculator Console Application" << endl << endl;
        cout << "Please enter the operation to perform. Format: a+b | a-b | a*b | a/b"
             << endl;
    
        Calculator c;
        while (true)
        {
            cin >> x >> oper >> y;
            result = c.Calculate(x, oper, y);
            cout << "Result " << "of " << x << oper << y << " is: " << result << endl;
        }
    
        return 0;
    }
    

    了解代码

    • 由于 C++ 程序总是从 main() 函数开始,我们需要从这里调用其他代码,因此需要 #include 语句。
    • 声明了一些初始变量 xyoperresult,分别用于存储第一个数字、第二个数字、运算符和最终结果。 提供一些初始变量始终是最佳做法,这样可避免未定义的行为,此示例即是如此。
    • Calculator c; 行声明一个名为“c”的对象作为 Calculator 类的实例。 类本身只是计算器工作方式的蓝图;对象是进行数学运算的特定计算器。
    • while (true) 语句是一个循环。 只要 () 内的条件成立,循环内的代码就会一遍又一遍地执行。 由于条件简单地列为 true,它始终为 true,因此循环将永远运行。 若要关闭程序,用户必须手动关闭控制台窗口。 否则,程序始终等待新输入。
    • cin 关键字用于接受来自用户的输入。 假设用户输入符合所需规范,此输入流足够智能,可以处理在控制台窗口中输入的一行文本,并按顺序将其放入列出的每个变量中。 可以修改此行以接受不同类型的输入,例如,两个以上的数字,但还需要更新 Calculate() 函数来处理此问题。
    • c.Calculate(x, oper, y); 表达式调用前面定义的 Calculate 函数,并提供输入的输入值。 然后该函数返回一个存储在 result 中的数字。
    • 最后,将 result 输出到控制台,以便用户查看计算结果。

再次生成和测试代码

现在再次测试程序以确保一切正常。

  1. 按“Ctrl+F5”重建并启动应用 。

  2. 输入 5+5,然后按 Enter 。 验证结果是否为 10。

    显示程序运行结果的命令窗口的屏幕截图。

    应用输出消息:请输入要执行的运算。 格式:a+b | a-b | a*b | a/b。 用户输入了 5+5。 应用输出:5+5 的结果:10

调试应用

由于用户可以自由地在控制台窗口中输入任何内容,因此请确保计算器会处理意外输入。 现在调试程序,而不运行程序,以便可以逐步检查程序所执行的每一项操作。

在调试器中运行应用

  1. CalcuatorTutorial.cpp 中的 result = c.Calculate(x, oper, y); 行上设置断点。 若要设置断点,请在该行旁边编辑器窗口左边缘的灰色竖线上单击。 将显示一个红点。

    Visual Studio 编辑器的屏幕截图。代表断点的红点出现在行 result = c.Calculate(x, oper, y) 上。

    现在,当调试程序时,执行进程会暂停在该行。 我们已大概了解了该程序可用于简单案例。 由于不想每次调用 Calculate() 时都暂停执行,因此可以设置断点条件。

  2. 右键单击表示断点的红点,并选择“条件”。 在条件的编辑框中,输入 (y == 0) && (oper == '/')。 选择“关闭”按钮以保存断点条件。

    Visual Studio 的屏幕截图,其中显示了“断点设置”弹出窗口。

    断点的条件为:y==0 && oper == '/' 为 true。

    现在,当应用尝试除以 0 时,执行进程会在断点处暂停。

  3. 若要调试程序,请按 F5 或选择带绿色箭头图标的“本地 Windows 调试程序”工具栏按钮。 在控制台应用中,如果输入类似“5 - 0”的内容,程序将正常运行并继续运行。 但是,如果键入“10/0”,它会在断点处暂停。 你可以在运算符和数字之间放置任意数量的空格:cin 足够智能,可以适当地解析输入。

    Visual Studio 编辑器的屏幕截图。系统会在行 result = c.Calculate(x, oper, y); 的条件断点处停止程序执行。

调试器中有用的窗口

调试代码时,你可能会注意到会出现一些新窗口。 你可借助这些窗口提高调试体验。 了解一下“自动”窗口 。 显示的“自动”窗口指示,在当前行之前,变量的当前值至少使用了三行 。

Visual Studio 调试器“自动”窗口的屏幕截图。

oper 的值为 47 '/',结果为 5,x 为 10,y 为 0。

若要查看该函数的所有变量,请切换到“局部变量”窗口 。 可以在调试时修改这些变量的值,以查看它们对程序的影响。 在这种情况下,不必理会。

Visual Studio 中“局部变量”窗口的屏幕截图,显示调试时局部变量的当前值。

oper 的值为 47 '/',结果为 0,x 为 10,y 为 0。

还可以将鼠标悬停在代码中的变量上,以查看该变量在此时点暂停执行的位置的值。 请先单击编辑器窗口,确保其处于焦点位置。

工具提示的屏幕截图,其中显示了变量“oper”的值,即 47 或 '/'。

继续调试

  1. 左侧的黄色箭头表示当前的执行点。 当前行调用 Calculate,因此按 F11 以“单步执行”函数 。 现在,你就在 Calculate 函数的主体中执行代码。 请小心使用“单步执行”,因为它会单步执行你正在处理的行上的任何函数,包括标准库函数。 单步执行标准库没有问题,但你可能更想专注于你的代码而不是库代码。

  2. 现在执行点位于 Calculate 函数的开头,按 F10 移动到程序执行的下一行 。 F10 也称为“单步跳过” 。 可以使用“单步跳过”在行与行之间移动,而无需深入研究行的每个部分的详细信息 。 一般情况下,应使用“单步跳过”而不是“单步执行”,除非你希望深入研究从其他地方调用的代码(就像你访问 Calculate 的主体一样)。

  3. 继续使用 F10 “单步跳过”每一行,直到返回到另一个文件中的 main() 函数,然后停在 cout 行 。

    程序在按预期执行操作:取第一个数字,然后除以第二个数字。 在 cout 行,将鼠标悬停在 result 变量上,或在“自动”窗口中查看 result 。 它的值 inf 看起来似乎不正确,因此我们来修复此错误。 cout 行只输出存储在 result 中的任何值,因此当使用 F10 向前再执行一行时,控制台窗口将显示以下内容 :

    Visual Studio 调试控制台的屏幕截图,显示除以零运算的结果。

    应用输出:请输入要执行的运算。 格式:a+b | a-b | a*b | a/b。 用户输入了 5-0。 应用输出:结果为:5。 用户输入了 10/0。 应用输出:结果为:inf

    出现这种结果是因为未定义除以零运算,因此程序无法给请求的运算提供数值解。

修复“被零除”错误

让我们更简洁地处理除数为零的情况,让用户可以更轻松地了解问题。

  1. CalculatorTutorial.cpp 中,进行下列更改。 (借助“编辑并继续”调试器功能,你可以在编辑时让程序继续运行)。 在 cin >> x >> oper >> y; 后面添加一个 if 语句,以检查除数为零的情况,并在发生此情况时向用户输出消息。 否则会打印结果。

    // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //
    
    #include <iostream>
    #include "Calculator.h"
    
    using namespace std;
    
    int main()
    {
        double x = 0.0;
        double y = 0.0;
        double result = 0.0;
        char oper = '+';
    
        cout << "Calculator Console Application" << endl << endl;
        cout << "Please enter the operation to perform. Format: a+b | a-b | a*b | a/b" << endl;
    
        Calculator c;
        while (true)
        {
            cin >> x >> oper >> y;
            if (oper == '/' && y == 0)
            {
                cout << "Attempted to divide by zero!" << endl;
                continue;
            }
            else
            {
                result = c.Calculate(x, oper, y);
            }
            cout << "Result " << "of " << x << oper << y << " is: " << result << endl;
        }
    
        return 0;
    }
    
  2. 按 F5 一次。 程序将继续执行,直到它必须暂停以请求用户输入。 再次输入 10 / 0。 现在,将输出更有用的信息。 用户被要求输入更多内容,程序继续正常执行。

    控制台窗口的屏幕截图,显示了对除以零的情况实施更改后的最终输出。

    控制台窗口显示两行,第一行为:10/0 结果为:inf;第二行为:10/0 数学错误:尝试除以零。

    注意

    在调试模式下编辑代码时,有可能会遇到旧代码。 当调试器仍在运行旧代码并且尚未使用更改进行更新时,将发生这种情况。 调试器会显示一个对话框,通知你何时发生这种情况。 有时,你可能需要按 F5 来刷新正在执行的代码 。 特别是,如果在函数内部进行更改而执行点位于该函数内部,则需要退出该函数,然后再次返回该函数以获取更新的代码。 如果该操作不起作用,且你看到错误消息,则可以通过单击 IDE 顶部菜单下工具栏中的红色方块来停止调试,然后通过输入 F5 或通过选择工具栏上“停止”按钮旁的绿色“播放”箭头重新开始调试。

    “编辑并继续”可能失败的另一个原因是出现一条消息,显示“需要启用‘调试’->‘选项’->‘常规’下的‘要求源文件与原始版本完全匹配’设置...”要解决此问题,请在主菜单中选择“工具”>“选项”>“调试”>“常规”,并确保选中“要求源文件与原始版本完全匹配”。

    了解“运行”和“调试”快捷方式

    • 按 F5(或“调试”>“启动调试”)启动调试会话(如果尚未激活),并运行程序,直到到达断点或程序需要用户输入 。 如果不需要用户输入,也没有可用的断点,程序将终止,当程序运行结束时,控制台窗口将自动关闭。 如果要运行类似“Hello World”程序,请使用 Ctrl+F5 或在按下 F5 之前设置断点以保持窗口打开。
    • Ctrl+F5(或“调试”>“开始执行(不调试)”在不进入调试模式的情况下运行应用程序 。 此快捷方式比调试要略微快一些,并且在程序执行完成后控制台窗口仍保持打开状态。
    • F10(称为“单步跳过”步骤)可逐行迭代代码,并可视化代码的运行方式,以及执行每个步骤的变量值 。
    • F11(称为“单步执行”)的工作方式类似于“单步跳过”,只是它将单步执行在执行行上调用的任何函数 。 例如,如果正在执行的行调用了一个函数,按下 F11 可将指针移动到函数体中,这样就可以在返回开始的行之前遵循正在运行的函数代码 。 按 F10 可执行函数调用并移动到下一行;函数调用仍然会发生,但是程序不会暂停来显示它在做什么 。

关闭应用程序

  • 如果它仍在运行,请关闭计算器应用的控制台窗口。

添加 Git 源代码管理

现在你已经创建了应用,可能需要将它添加到 Git 存储库。 我们已经为你准备好了。 Visual Studio 通过 Git 工具简化了该过程,你可直接从 IDE 中使用这些工具。

提示

Git 是使用最广泛的新式版本控制系统,因此无论你是专业开发人员,还是正在学习如何编码,Git 都非常有用。 如果你是刚刚接触 Git,可访问 https://git-scm.com/ 网站开始了解。 在这里,你能找到速查表、畅销在线图书和 Git 基础知识视频。

若要将代码与 Git 关联,需要首先创建一个新的 Git 存储库来容纳代码。 下面介绍如何操作:

  1. 在 Visual Studio 右下角的状态栏中,选择“添加到源代码管理”,然后选择“Git” 。

    “解决方案资源管理器”窗格下的 Git 源代码管理按钮的屏幕截图,其中突出显示了“添加到源代码管理”按钮。

  2. 在“创建 Git 存储库”对话框中,登录到 GitHub。

    “创建 Git 存储库”对话框窗口的屏幕截图,可在其中创建新的 GitHub 存储库。

    存储库名称根据你的文件夹位置自动填充。 默认情况下,新存储库是专用的,这意味着只有你可以访问它。

    提示

    无论存储库是公用的还是专用的,都最好将代码的远程备份安全地存储在 GitHub 上。 即使你不与团队合作,也可使用任意计算机上在远程存储库中访问你的代码。

  3. 选择“创建并推送”。

    创建存储库后,状态栏中会显示状态详细信息。

    位于 Visual Studio 解决方案资源管理器窗格下方的存储库状态栏的屏幕截图,其中显示分支名称和未完成更改的数量。

    带箭头的第一个图标显示当前分支中的传出/传入提交数。 可以使用此图标来拉取任何传入提交或推送任何传出提交。 还可选择先查看这些提交。 为此,请选择图标,然后选择“查看传出/传入”。

    带铅笔的第二个图标显示代码的未提交更改数。 可选择此图标,在“Git 更改”窗口中查看这些更改。

若要详细了解如何在应用中使用 Git,请参阅 Visual Studio 版本控制文档

完成的应用

祝贺你! 你已经完成计算器应用的代码,生成并调试了它,还将它添加到了存储库 - 所有这些操作都在 Visual Studio 中完成。

后续步骤

了解有关 Visual Studio for C++ 的更多信息

C++ 程序员通常从在命令行上运行的“Hello, world!”应用程序开始。 你将以本文为起点,逐步进阶,加深学习难度:计算器应用。

先决条件

创建应用项目

Visual Studio 使用项目来组织应用的代码,使用解决方案来组织一个或多个项目。 项目包含用于生成应用的所有选项、配置和规则。 它还负责管理所有项目文件和任何外部文件间的关系。 若要创建应用,先创建一个新项目和解决方案。

  1. 在 Visual Studio 中的菜单栏上,选择“文件”>“新建”>“项目”。 随即将打开“新建项目”窗口 。

  2. 在左侧边栏上,确保选中“Visual C++” 。 选择中间的“Windows 控制台应用程序”

  3. 在底部的“名称”文本框中,将新项目命名为“CalculatorTutorial”,然后选择“确定”

    “新建项目”对话框的屏幕截图。已选中“Windows 控制台应用程序”项目类型。“名称”文本框设置为 CalculatorTutorial。

    将创建一个空的 C++ Windows 控制台应用程序“Hello World”应用。 控制台应用程序使用 Windows 控制台窗口显示输出并接受用户输入。 在 Visual Studio 中,将打开一个编辑器窗口并显示生成的代码:

    // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //
    
    #include <iostream>
    
    int main()
    {
        std::cout << "Hello World!\n";
    }
    
    // Run program: Ctrl + F5 or Debug > Start Without Debugging menu
    // Debug program: F5 or Debug > Start Debugging menu
    
    // Tips for Getting Started:
    //   1. Use the Solution Explorer window to add/manage files
    //   2. Use the Team Explorer window to connect to source control
    //   3. Use the Output window to see build output and other messages
    //   4. Use the Error List window to view errors
    //   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
    //   6. In the future, to open this project again, go to File > Open > Project and select the .sln file
    

验证新应用是否生成并运行

新的 Windows 控制台应用程序模板创建了一个简单的 C++“Hello World”应用。 此时,可以看到 Visual Studio 如何生成并运行直接从 IDE 创建的应用。

  1. 若要生成项目,请从“生成”菜单选择“生成解决方案”。 “输出”窗口将显示生成过程的结果 。

    Visual Studio 输出窗口的屏幕截图,其中显示生成已成功。

  2. 若要运行代码,请在菜单栏上依次选择“调试”、“开始执行(不调试)”(Ctrl+F5)。

    Visual Studio 调试控制台的屏幕截图,其中显示输出“Hello World!”

    随即将打开控制台窗口,然后运行你的应用。

    在 Visual Studio 中启动控制台应用时,它会运行代码,然后输出“按任意键关闭此窗口。 。 .”,让你有机会看到输出。

    祝贺你! 你在 Visual Studio 中创建了首个“Hello, world!”控制台应用!

  3. 按任意键关闭该控制台窗口并返回到 Visual Studio。

现在即可使用你的工具在每次更改后生成并运行应用,以验证代码是否仍按预期运行。 如果未按预期运行,稍后我们将向你演示调试方法。

编辑代码

现在,将此模板中的代码转换为计算器应用。

  1. CalculatorTutorial.cpp 文件的内容替换为以下代码,使其与本示例一致:

    // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //
    
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        cout << "Calculator Console Application" << endl << endl;
        cout << "Please enter the operation to perform. Format: a+b | a-b | a*b | a/b" << endl;
        return 0;
    }
    
    // Run program: Ctrl + F5 or Debug > Start Without Debugging menu
    // Debug program: F5 or Debug > Start Debugging menu
    // Tips for Getting Started:
    //   1. Use the Solution Explorer window to add/manage files
    //   2. Use the Team Explorer window to connect to source control
    //   3. Use the Output window to see build output and other messages
    //   4. Use the Error List window to view errors
    //   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
    //   6. In the future, to open this project again, go to File > Open > Project and select the .sln file
    

    了解代码:

    • #include 语句允许引用位于其他文件中的代码。 有时,文件名使用尖括号 (<>) 括起来;其他情况下,使用引号 (" ") 括起来。 通常,引用 C++ 标准库时使用尖括号,引用其他文件时使用引号。
    • using namespace std; 行提示编译器期望在此文件中使用 C++ 标准库中的内容。 如果没有这一行,库中的每个关键字都必须以 std:: 开头,以表示其范围。 例如,如果没有该行,则对 cout 的每个引用都必须写为 std::coutusing 语句的使用是为了使代码看起来更干净。
    • cout 关键字用于在 C++ 中打印到标准输出。 *<< 运算符提示编译器将其右侧的任何内容发送到标准输出。
    • endl 关键字与 Enter 键类似;用于结束该行并将光标移动到下一行。 如果要执行相同的操作,最好在字符串中使用 \n(用 "" 包含),因为使用 endl 会始终刷新缓冲,可能会影响程序的性能。 但是,由于这是一个非常小的应用,所以改为使用 endl 以提高可读性。
    • 所有 C++ 语句都必须以分号结尾,所有 C++ 应用程序都必须包含 main() 函数。 该函数是程序开始运行时运行的函数。 若要使用所有代码,必须可从 main() 访问所有代码。
  2. 要保存文件,请按下 Ctrl+S,或者选择 IDE 顶部附近的“保存”图标,即菜单栏下工具栏中的软盘图标

  3. 要运行该应用程序,请按“Ctrl+F5”或转到“调试”菜单,然后选择“启动但不调试”。 如果看到“此项目已过期”弹出窗口,可选择“不再显示此对话框”,然后选择“是”生成应用程序。 应会显示一个控制台窗口,其中显示代码中指定的文本。

    视频显示了在 IDE 中运行计算器应用的过程。

    首先显示一个对话框,询问是否构建,因为该项目已过期。 勾选“不再显示此对话框”的复选框。 选择“是”以生成项目,生成计算器项目,然后在 Windows 控制台窗口中启动该项目。

  4. 完成后,请关闭控制台窗口。

添加代码来执行一些数学运算

类就像执行某事的对象的蓝图。 在这种情况下,我们将定义一个计算器类来包含数学逻辑。

添加 Calculator 类

  1. 转到“项目”菜单,然后选择“添加类”。 在“类名”编辑框中,输入“Calculator” 。 选择“确定”

    显示用户打开“添加类”对话框,在“类名称”字段中键入 Calculator,然后点击“确定”的视频。

    类就像执行某事的对象的蓝图。 在本示例中,我们定义了 Calculator 以及它的工作原理。

    这会向项目中添加两个新文件。 若要同时保存所有已更改的文件,请按“Ctrl+Shift+S” 。 这是“文件”>“全部保存”的键盘快捷方式 。 在“保存”按钮旁边还有一个用于“全部保存”的工具栏按钮,这是两个软盘的图标 。 一般来说,最好经常使用“全部保存”,这样你保存时就不会遗漏任何文件 。

    “添加类”向导创建与该类同名的 .h.cpp 文件。 可以在 IDE 一侧的“解决方案资源管理器”窗口中看到项目文件的完整列表 。 如果该窗口不可见,则可从菜单栏中打开它:选择“查看”>“解决方案资源管理器”

    Visual Studio 解决方案资源管理器窗口的屏幕截图。

    计算器教程项目有一个头文件节点,其中包含 Calculator.h、stdafx.h 和 targetver.h。 源文件节点包含 Calculator.cpp、CalculatorTutorial.cpp 和 stdafx.cpp。 引用、外部依赖项和资源文件的节点可见,但处于关闭状态。

    可通过在“解决方案资源管理器”窗口中双击文件将其打开。 双击 Calculator.h 将其打开。

  2. Calculator.h 的内容替换为以下代码,使文件现在如下所示:

    #pragma once
    class Calculator
    {
    public:
        double Calculate(double x, char oper, double y);
    };
    

    了解代码

    • 此代码声明了一个名为 Calculate 的新函数,我们将使用它来运行加法、减法、乘法和除法的数学运算。
    • C ++ 代码被组织成标头 (.h) (.h) 文件和源 (.cpp) 文件。 所有类型的编译器都支持其他几个文件扩展名,但这些是要了解的主要文件扩展名。 函数和变量通常在头文件中进行声明(即在头文件中指定名称和类型)和实现(或在源文件中指定定义) 。 若要访问在另一个文件中定义的代码,可以使用 #include "filename.h",其中 filename.h 是声明要使用的变量或函数的文件的名称。
    • 最好根据代码的功能将代码组织到不同的文件中,方便稍后需要这些代码时能够轻易查找到。 在本例中,我们分别定义了 Calculator 类和包含 main() 函数的文件,但我们计划在 main() 中引用 Calculator 类。
  3. Calculate 下方会出现绿色波浪线,因为尽管已声明 Calculate 函数,但并未定义该函数。 将鼠标悬停在 Calculate 上,单击显示的螺丝刀上的向下箭头,然后选择“在 Calculator.cpp 中创建 "Calculate" 定义”。 随即将出现一个弹出窗口,可在其中查看在另一个文件中进行的代码更改。 该代码已添加到 Calculator.cpp

    显示使用灯泡图标下拉列表选择“在 Calculator.cpp 中创建 Calculate 定义”的视频。

    目前,它只返回 0.0。 让我们来更改它。 按 Esc 关闭弹出窗口 。

  4. 切换到编辑器窗口中的 Calculator.cpp 文件。 将文件的内容替换为以下代码:

    #include "Calculator.h"
    
    double Calculator::Calculate(double x, char oper, double y)
    {
        switch(oper)
        {
            case '+':
                return x + y;
            case '-':
                return x - y;
            case '*':
                return x * y;
            case '/':
                return x / y;
            default:
                return 0.0;
        }
    }
    

    了解代码

    • 函数 Calculate 使用数字、运算符和第二个数字,然后对数字执行请求的操作。
    • Switch 语句检查提供了哪个运算符,并仅执行与该操作对应的情况。 “default: case”是一个回滚,以防用户键入一个不被接受的运算符,因此程序不会中断。 通常,最好以更简洁的方式处理无效的用户输入,但这超出了本教程的范围。
    • double 关键字表示支持小数的数字类型。 因此,Calculator 可以处理十进制数学和整数数学。 要始终返回这样的数字,需要 Calculate 函数,因为代码的最开始是 double(这表示函数的返回类型),这就是为什么我们在默认情况下返回 0.0。
    • .h 文件声明函数“prototype”,它预先告诉编译器它需要什么参数,以及期望它返回什么样的返回类型。 .cpp 文件包含该函数的所有实现细节。

如果此时再次生成并运行代码,则在询问要执行的操作后,它仍然会退出。 接下来,修改 main 函数以进行一些计算。

调用 Calculator 类的成员函数

  1. 现在让我们更新 CalculatorTutorial.cpp 中的 main 函数:

    // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //
    
    #include <iostream>
    #include "Calculator.h"
    
    using namespace std;
    
    int main()
    {
        double x = 0.0;
        double y = 0.0;
        double result = 0.0;
        char oper = '+';
    
        cout << "Calculator Console Application" << endl << endl;
        cout << "Please enter the operation to perform. Format: a+b | a-b | a*b | a/b" << endl;
    
        Calculator c;
        while (true)
        {
            cin >> x >> oper >> y;
            result = c.Calculate(x, oper, y);
            cout << "Result is: " << result << endl;
        }
    
        return 0;
    }
    

    了解代码

    • 由于 C++ 程序总是从 main() 函数开始,我们需要从这里调用其他代码,因此需要 #include 语句。
    • 声明了一些初始变量 xyoperresult,分别用于存储第一个数字、第二个数字、运算符和最终结果。 提供一些初始变量始终是最佳做法,这样可避免未定义的行为,此示例即是如此。
    • Calculator c; 行声明一个名为“c”的对象作为 Calculator 类的实例。 类本身只是计算器工作方式的蓝图;对象是进行数学运算的特定计算器。
    • while (true) 语句是一个循环。 只要 () 内的条件成立,循环内的代码就会一遍又一遍地执行。 由于条件简单地列为 true,它始终为 true,因此循环将永远运行。 若要关闭程序,用户必须手动关闭控制台窗口。 否则,程序始终等待新输入。
    • cin 关键字用于接受来自用户的输入。 假设用户输入符合所需规范,此输入流足够智能,可以处理在控制台窗口中输入的一行文本,并按顺序将其放入列出的每个变量中。 可以修改此行以接受不同类型的输入,例如,两个以上的数字,但还需要更新 Calculate() 函数来处理此问题。
    • c.Calculate(x, oper, y); 表达式调用前面定义的 Calculate 函数,并提供输入的输入值。 然后该函数返回一个存储在 result 中的数字。
    • 最后,将 result 输出到控制台,以便用户查看计算结果。

再次生成和测试代码

再次测试程序以确保一切正常。

  1. 按“Ctrl+F5”重建并启动应用 。

  2. 输入 5+5,然后按 Enter 。 验证结果是否为 10。

    运行计算器应用的命令窗口的屏幕截图。它显示 5 + 5 的结果为 10。

调试应用

由于用户可以自由地在控制台窗口中输入任何内容,因此请确保计算器会处理意外输入。 现在调试程序,不运行程序,以便可以逐步检查程序所执行的每一项操作。

在调试器中运行应用

  1. CalcuatorTutorial.cpp 中的 result = c.Calculate(x, oper, y); 行上设置断点。 若要设置断点,请在该行旁边编辑器窗口左边缘的灰色竖线上单击。 将显示一个红点。

    视频显示用户在第 25 行 result = c.Calculate(x, oper, y); 设置断点。

    现在,当我们调试程序时,它总是暂停该行的执行。 我们已大概了解了该程序可用于简单案例。 由于我们不想每次暂停执行,因此可以设置断点条件。

  2. 右键单击表示断点的红点,并选择“条件”。 在条件的编辑框中,输入 (y == 0) && (oper == '/')。 完成后,选择“关闭”按钮以保存断点条件。

    演示设置条件断点过程的视频。

    断点位于 result = c dotCalculate(x, oper, y) 行。 在断点下拉菜单中选择“条件…”,执行此操作会打开断点设置窗口。 选中“条件”选项,在其下方的下拉菜单中,采取以下设置:“条件表达式”和“为 true”。 用户在条件文本框中输入 y == 0 && oper == '/',然后选择“关闭”以设置条件断点。

    现在,如果尝试被 0 除,我们将在断点处暂停执行。

  3. 若要调试程序,请按 F5 或选择带绿色箭头图标的“本地 Windows 调试程序”工具栏按钮。 在控制台应用中,如果输入类似“5 - 0”的内容,程序将正常运行并继续运行。 但是,如果键入“10/0”,它会在断点处暂停。 你甚至可以在运算符和数字之间放置任意数量的空格;cin 足够智能,可以适当地解析输入。

    显示程序执行在条件断点处暂停的视频。

    用户输入 5 - 0。 应用输出:结果为 5。 然后,用户输入 10/0,由于满足条件断点的条件,因此执行将在行 result = c.Calculate(x, oper, y); 处停止

调试器中有用的窗口

调试代码时,你可能会注意到会出现一些新窗口。 你可借助这些窗口提高调试体验。 了解一下“自动”窗口 。 显示的“自动”窗口指示,在当前行之前,变量的当前值至少使用了三行 。

Visual Studio 调试器“自动”窗口的屏幕截图。

oper 的值为 47 '/',结果为 5,x 为 10,y 为 0。

若要查看该函数的所有变量,请切换到“局部变量”窗口 。 可以在调试时修改这些变量的值,以查看它们对程序的影响。 在这种情况下,不必理会。

Visual Studio 中“局部变量”窗口的屏幕截图,显示调试时局部变量的当前值。

oper 的值为 47 '/',结果为 0,x 为 10,y 为 0。

也可将鼠标悬停在代码本身中的变量上,以查看该变量在当前暂停执行位置的当前值。 请先单击编辑器窗口,确保其处于焦点位置。

将鼠标悬停在变量 y 上时会出现工具提示的演示视频。它显示 y 的当前值,即 0。

继续调试

  1. 左侧的黄色箭头表示当前的执行点。 当前行调用 Calculate,因此按 F11 以“单步执行”函数,这会将你引入 Calculate 函数的主体。 请小心使用“单步执行”,因为它会单步执行你正在处理的行上的任何函数,包括标准库函数。 单步执行标准库没有问题,但你可能更想专注于你的代码而不是库代码。

  2. 现在执行点位于 Calculate 函数的开头,按 F10 移动到程序执行的下一行 。 F10 也称为“单步跳过” 。 可以使用“单步跳过”在行与行之间移动,而无需深入研究行的每个部分的详细信息 。 一般情况下,应使用“单步跳过”而不是“单步执行”,除非希望深入研究从其他地方调用的代码(就像你访问 Calculate 的主体一样) 。

  3. 继续使用 F10 “单步跳过”每一行,直到返回到另一个文件中的 main() 函数,然后停在 cout 行 。

    逐过程执行 Calculate 函数各个代码行的视频。

    系统会逐过程执行 Calculate 函数中的每个代码行,直到控件返回到主函数。 然后,用户将鼠标悬停在名为 result 的变量上以查看其值,即:inf。

    程序在按预期执行操作:取第一个数字,然后除以第二个数字。 在 cout 行,将鼠标悬停在 result 变量上,或在“自动”窗口中查看 result 。 它的值是 inf,看起来似乎不正确,因此我们来修复此错误。 cout 行只输出存储在 result 中的任何值,因此当使用 F10 向前再执行一行时,控制台窗口将显示以下内容 :

    Visual Studio 调试控制台的屏幕截图,显示除以零运算的结果。

    应用输出:请输入要执行的运算。 格式:a+b | a-b | a*b | a/b。 用户输入了 5-0。 应用输出:结果为:5。 用户输入了 10/0。 应用输出:结果为:inf

    出现这种结果是因为未定义除以零运算,因此程序无法给请求的运算提供数值解。

修复“被零除”错误

让我们更简洁地处理除数为零的情况,让用户可以更轻松地了解问题。

  1. CalculatorTutorial.cpp 中,进行下列更改。 (借助“编辑并继续”调试器功能,你可以在编辑时让程序继续运行)。 变化是在 cin >> x >> oper >> y; 后面添加一个 if 语句,以检查除数为零的情况,并在发生此情况时向用户输出消息。 否则会打印结果:

    // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //
    
    #include <iostream>
    #include "Calculator.h"
    
    using namespace std;
    
    int main()
    {
        double x = 0.0;
        double y = 0.0;
        double result = 0.0;
        char oper = '+';
    
        cout << "Calculator Console Application" << endl << endl;
        cout << "Please enter the operation to perform. Format: a+b | a-b | a*b | a/b" << endl;
    
        Calculator c;
        while (true)
        {
            cin >> x >> oper >> y;
            if (oper == '/' && y == 0)
            {
                cout << "Division by 0 exception" << endl;
                continue;
            }
            else
            {
                result = c.Calculate(x, oper, y);
            }
            cout << "Result is: " << result << endl;
        }
    
        return 0;
    }
    
  2. 按 F5 一次。 程序将继续执行,直到它必须暂停以请求用户输入。 再次输入 10 / 0。 现在,将输出更有用的信息。 用户被要求输入更多内容,程序继续正常执行。

    调试控制台的视频,其中显示代码更改后的最终结果。输入 10 / 0,程序显示“执行除以 0 运算出现异常”。

    注意

    在调试模式下编辑代码时,有可能会遇到旧代码。 当调试器仍在运行旧代码并且尚未使用更改进行更新时,将发生这种情况。 调试器会弹出一个对话框,通知你何时发生这种情况。 有时,你可能需要按 F5 来刷新正在执行的代码 。 特别是,如果在函数内部进行更改而执行点位于该函数内部,需要退出该函数,然后再次返回该函数以获取更新的代码。 如果由于某种原因该操作不起作用,且你看到错误消息,则可以通过单击 IDE 顶部菜单下工具栏中的红色方块来停止调试,然后通过输入 F5 或通过选择工具栏上“停止”按钮旁的绿色“播放”箭头重新开始调试。

    “编辑并继续”可能失败的另一个原因是,需要转到主菜单,并依次选择“工具”>“选项”>“调试”>“常规”,并确保选中“要求源文件与原始版本完全匹配”

    了解“运行”和“调试”快捷方式

    • 按 F5(或“调试”>“启动调试”)启动调试会话(如果尚未激活),并运行程序,直到到达断点或程序需要用户输入 。 如果不需要用户输入,也没有可用的断点,程序将终止,当程序运行结束时,控制台窗口将自动关闭。 如果要运行类似“Hello World”程序,请使用 Ctrl+F5 或在按下 F5 之前设置断点以保持窗口打开。
    • Ctrl+F5(或“调试”>“开始执行(不调试)”在不进入调试模式的情况下运行应用程序 。 此快捷方式比调试要略微快一些,并且在程序执行完成后控制台窗口仍保持打开状态。
    • F10(称为“单步跳过”步骤)可逐行迭代代码,并可视化代码的运行方式,以及执行每个步骤的变量值 。
    • F11(称为“单步执行”)的工作方式类似于“单步跳过”,只是它将单步执行在执行行上调用的任何函数 。 例如,如果正在执行的行调用了一个函数,按下 F11 可将指针移动到函数体中,这样就可以在返回开始的行之前遵循正在运行的函数代码 。 按 F10 可执行函数调用并移动到下一行;函数调用仍然会发生,但是程序不会暂停来显示它在做什么 。

关闭应用程序

  • 如果它仍在运行,请关闭计算器应用的控制台窗口。

祝贺你! 你已经完成计算器应用的代码,并在 Visual Studio 中生成和调试了该代码。

后续步骤

了解有关 Visual Studio for C++ 的更多信息