C++基础3:C++的数组和函数

此专栏为移动机器人知识体系下的编程语言中的 C {\rm C} C++从入门到深入的专栏,参考书籍:《深入浅出 C {\rm C} C++》(马晓锐)和《从 C {\rm C} C C {\rm C} C++精通面向对象编程》(曾凡锋等)。



3.C++的数组和函数
3.1 一维数组概述
  • 一维数组定义和初始化。

    // 1.数组是一组相同类型数据的集合,数组中的每一个元素通过下标表示其在数组中的位置;
    
    // 2.一维数组的定义格式:
    数据类型  数组名[常量表达式];
    
    // 2.1 数据类型:数组中元素的类型;
    // 2.2 数组名:该数组的名称;
    // 2.3 常量表达式:表示数组中元素的个数,必须是一个整数;
    
    // 3.定义数组时对数组进行初始化;
    // 3.1 对数组中所有元素赋值;
    // 初始化赋值的一般形式:
    数据类型  数组名[常量表达式]={值,值,...,值};
    int array1[] = {1,2,3,4,5};
    int array2[5] = {1,2,3,4,5};
    
    // 3.2 对数组中部分元素赋值;
    int array3[5] = {1,2,3};
    
  • 一维数组的引用。

    // 数组必须先声明后使用,数组中元素由数组名和下标唯一标识的;
    
    // 数组元素的一般引用形式:
    数组名[下标表达式]
    
  • 一维数组的内存结构和寻址。

    • 数组在内存中占有内存单元,它们存在于一组连续的存储单元中;

    • 定义数组:

      int array[5]={1,2,3,4,5};
      
    • 上述数组存储结构如下:

      5

    • 编译器在内存中开辟长度为 5 5 5的区域,假设整型数据占两字节,该数组的起始地址为: 8000 8000 8000,如上数组内存分配如下表:

      内存地址 内存地址 内存地址 内容 内容 内容
      8000 8000 8000 1 1 1
      8002 8002 8002 2 2 2
      8004 8004 8004 3 3 3
      8006 8006 8006 4 4 4
      8008 8008 8008 5 5 5
    • 数组中元素在内存中按顺序依次存放,地址是连续的;

    • 数组名是该数组的起始地址,即 a [ 0 ] {\rm a[0]} a[0]元素的地址;

    • 数组是按顺序存储的,元素寻址计算公式如下:

      addr[i]=addr[0]+i*w
          
      // addr[i]:表示数组中第i个元素的地址;
      // w:表示每个元素占据的存储空间大小;
      
3.2 二维数组概述
  • 二维数组的定义和初始化。

    // 1.二维数组的定义格式:
    数据类型 数组名[常量表达式1][常量表达式2];
    
    // 常量表达式1表示第一维长度,称为行;
    // 常量表达式2表示第二维长度,称为列;
    int a[4][3];	// 定义一个大小为:4×3的二维整型数组;
    
    // 2.按行对二维数组初始化;
    int a[2][3] = {{1,2,3},{4,5,6}};
    
    // 3.按数组排列顺序对二维数组初始化;
    int a[2][3] = {1,2,3,4,5,6};
    
    // 4.对二维数组中部分元素初始化;
    int a[2][3] = {{1},{4}};
    
    // 5.维度省略:对所有元素初始化时,可以不指定第一维的长度,但第二维度的长度不可省略;
    int a[][3] = {1,2,3,4,5,6};
    
  • 二维数组的引用。

    // 1.二维数组引用格式:
    数组名[下标表达式1][下标表达式2]
    
  • 实例 ( e x a m p l e 3 _ 1. c p p ) ({\rm example3\_1.cpp}) (example3_1.cpp):求二维数组的最小值。

    /**
     * 作者:罗思维
     * 时间:2023/10/08
     * 描述:求二维数组中的最小值。
     */
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int array[2][3] = {{1, 2, 3}, {4, 5, 6}};
        int arrayMin = array[0][0]; // 假设二维数组中第一个元素为最小值;
    
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (array[i][j] < arrayMin)
                {
                    arrayMin = array[i][j];
                }
            }
        }
    
        cout << "二维数组中的最小值为:" << arrayMin << endl;
    
        return 0;
    }
    
  • 二维数组的内存寻址。

    二维数组 a [ m ] [ n ] {\rm a[m][n]} a[m][n]中元素的寻址计算公式: a d d r [ i ] [ j ] = a d d r [ 0 ] [ 0 ] + ( i × n + j ) × w {\rm addr[i][j]=addr[0][0]+(i\times{n}+j)\times{w}} addr[i][j]=addr[0][0]+(i×n+j)×w n {\rm n} n为二维数组中第二维的维数, w {\rm w} w为每个元素所占存储空间的大小。

3.3 多维数组概述
  • 多维数组的定义和初始化。

    // 1.多维数组定义格式:
    类型标识符 数组名[常量表达式1][常量表达式2][常量表达式3]...
    int a[2][3][4];
    float f[2][3][4][5];
    
    // 2.多维数组初始化:
    int a[2][3][2] = {{{1,2},{3,4},{5,6}},{{7,8},{9,10},{11,12}}};
    int a[2][3][2] = {1,2,3,4,5,6,7,8,9,10,11,12};
    int a[2][3][2] = {{{1},{3},{5}},{{7},{9},{11}}};
    int a[][3][2] = {1,2,3,4,5,6,7,8,9,10,11,12};
    
  • 多维数组的引用。

    // 1.多维数组的引用格式:
    数组名[下标表达式1][下标表达式2][下标表达式3]...
    
  • 三维数组的内存寻址。

    三维数组 a [ m ] [ n ] [ a ] {\rm a[m][n][a]} a[m][n][a]中元素的寻址计算公式: a d d r [ i ] [ j ] [ k ] = a d d r [ 0 ] [ 0 ] [ 0 ] + ( i ∗ n + j ∗ a + k ) ∗ w {\rm addr[i][j][k]=addr[0][0][0]+(i*n+j*a+k)*w} addr[i][j][k]=addr[0][0][0]+(in+ja+k)w n {\rm n} n为第二维维数, a {\rm a} a为第三维维数, w {\rm w} w为每个元素所占的内存大小。

3.4 字符数组概述
  • 字符数组定义:用来存放字符量的数组称为字符数组,即字符数组中每一个元素都是字符类型;

  • 字符数组的定义和初始化:

    // 1.定义字符数组:
    char c[12];			// 定义一维字符数组;
    char c[3][4];		// 定义二维字符数组;
    
    // 2.字符数组初始化;
    char c[12] = {'W','i','l','l','a','r','d'};
    char c[] = {'W','i','l','l','a','r','d'};
    
  • 字符数组的引用 ( e x a m p l e 3 _ 2. c p p ) ({\rm example3\_2.cpp}) (example3_2.cpp):通过下标引用。

    /**
     * 作者:罗思维
     * 时间:2023/10/08
     * 描述:定义一个字符数组,输出字符数组的内容。
     */
    #include <iostream>
    using namespace std;
    
    int main()
    {
        char charArray[5][5] = {{'J', 'i', 'n', 'D', 'i'}, {'S', 'i', 'W', 'e', 'i'}};
    
        for (int i = 0; i < 5; i++)
        {
            for (int j = 0; j <= 4; j++)
            {
                cout << charArray[i][j];
            }
            cout << endl;
        }
    
        return 0;
    }
    
  • 利用字符数组操作字符串。

    字符串以’\ 0 0 0’作为结束符,当把一个字符串存入一个数组时,结束符’\ 0 0 0’也存入了数组,并以此作为该字符串结束的标志。

    // 1.用字符串对数组初始化。
    char c[] = {"Willard"};
    char c[] = "Willard";
    
    // 2.C++中的memset()函数原型如下:
    void *memset(void *dest,int c,size_t count);
    
    // 参数说明:
    // dest:目标缓冲区,即需要处理的字符串变量;
    // c:要设置的字符,即将目标缓冲区每一个地址(元素)上的值设置为这个字符;
    // count:字节数,即缓冲区的长度;
    
    // example3_3.cpp
    /**
     * 作者:罗思维
     * 时间:2023/10/08
     * 描述:格式化字符数组。
     */
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    int main()
    {
        char str[10];
        memset(str, 0x00, sizeof(str)); // 字符数组格式化,全部赋值为空;
        cout << str << endl;            // 输出内容为空;
    
        return 0;
    }
    
3.5 实战1

项目需求:用 C {\rm C} C++实现两个矩阵的乘法运算。

需求分析:矩阵乘法运算规律 M m 1 × n 1 × N n 1 × n 2 = Q m 1 × n 2 {\rm M_{m_1\times{n_1}}\times{N_{n_1\times{n_2}}}=Q_{m_1\times{n_2}}} Mm1×n1×Nn1×n2=Qm1×n2,矩阵 M {\rm M} M的列数必须等于矩阵 N {\rm N} N的函数,矩阵 Q {\rm Q} Q的行数等于矩阵 M {\rm M} M的列数,列数等于矩阵 N {\rm N} N的列数。

代码实现 ( p r o j e c t 3 _ 1. c p p ) ({\rm project3\_1.cpp}) (project3_1.cpp):

/**
 * 作者:罗思维
 * 时间:2023/10/08
 * 描述:实现两个矩阵的乘法运算。
 */
#include <iostream>
using namespace std;

int main()
{
    int arrayM[3][4] = {{1, 2, 3, 4}, {3, 4, 5, 6}, {7, 8, 9, 2}};
    int arrayN[4][3] = {{8, 7, 6}, {1, 3, 4}, {5, 6, 7}, {8, 9, 6}};
    int i, j, k;
    int arrayQ[3][3] = {{0}, {0}, {0}};

    // 输出矩阵M的元素
    cout << "矩阵M如下所示:" << endl;
    cout << "===========================" << endl;

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j <= 3; j++)
        {
            cout << arrayM[i][j] << "\t";
        }
        cout << endl;
    }
    cout << "===========================" << endl;

    // 输出矩阵N的元素
    cout << "矩阵N如下所示:" << endl;
    cout << "===========================" << endl;

    for (i = 0; i < 4; i++)
    {
        for (j = 0; j <= 2; j++)
        {
            cout << arrayN[i][j] << "\t";
        }
        cout << endl;
    }
    cout << "===========================" << endl;

    // 对矩阵进行乘法运算;
    cout << "矩阵Q如下所示:" << endl;
    cout << "===========================" << endl;

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            for (k = 0; k < 4; k++)
            {
                // 将对应的行和列相应元素相乘并累加;
                arrayQ[i][j] = arrayQ[i][j] + arrayM[i][k] * arrayN[k][j];
            }
        }
    }

    // 输出目标矩阵的元素;
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            cout << arrayQ[i][j] << "\t";
        }
        cout << endl;
    }

    return 0;
}
3.6 函数概述和定义
  • 函数可以看作程序员定义的功能模块,每个函数都实现一系列的操作,一个程序可以包含若干个函数,但只有一个 m a i n {\rm main} main函数,程序总是从 m a i n {\rm main} main函数处开始执行;

  • 调用函数前必须先定义函数,函数定义由返回值类型、函数名、参数列表和函数体构成;

  • 函数定义格式:

    返回值类型 函数名(参数列表)
    {
        语句序列;
        return 返回类型的值;
    }
    
    • 返回值类型:函数一般有返回值,在函数名前声明其返回值类型,若无返回值,则返回值类型用 v o i d {\rm void} void
    • 函数名:要定义的函数名字,函数命名遵循一定的规则,且要有意义,尽量用英文表达出函数完成的功能;
    • 参数列表:当调用函数时输入的值称为实参(实际参数),定义函数时的参数称为形参(形式参数);
    • 函数体:函数要执行的操作,当返回类型为 v o i d {\rm void} void时,函数体不需要 r e t u r n {\rm return} return语句;
  • 实例 ( e x a m p l e 3 _ 4. c p p ) ({\rm example3\_4.cpp}) (example3_4.cpp):根据输入字母,实现加减乘除计算。

    /**
     * 作者:罗思维
     * 时间:2023/10/08
     * 描述:用函数实现简易的计算器。
     */
    #include <iostream>
    using namespace std;
    
    // 函数声明
    void calcAdd(float a, float b);
    void calcSub(float a, float b);
    void calcMul(float a, float b);
    void calcDiv(float a, float b);
    
    int main()
    {
        char flag;
        float number1, number2;
    
        cout << "请输入两个数:";
        cin >> number1 >> number2;
    
        cout << "请输入何种计算类型(A:加法,S:减法,M:乘法,D:除法,T:全部):";
        cin >> flag;
    
        switch (flag)
        {
        case 'A':
            calcAdd(number1, number2);	// 函数调用;
            break;
        case 'S':
            calcSub(number1, number2);
            break;
        case 'M':
            calcMul(number1, number2);
            break;
        case 'D':
            calcDiv(number1, number2);
            break;
        case 'T':
            calcAdd(number1, number2);
            calcSub(number1, number2);
            calcMul(number1, number2);
            calcDiv(number1, number2);
            break;
        default:
            break;
        }
    
        return 0;
    }
    
    // 函数定义
    void calcAdd(float a, float b)
    {
        float addResult = 0;
        addResult = a + b;
    
        cout << "number1 + number2 = " << addResult << endl;
    }
    
    void calcSub(float a, float b)
    {
        float subResult = 0;
        subResult = a - b;
    
        cout << "number1 - number2 = " << subResult << endl;
    }
    
    void calcMul(float a, float b)
    {
        float mulResult = 0;
        mulResult = a * b;
    
        cout << "number1 * number2 = " << mulResult << endl;
    }
    
    void calcDiv(float a, float b)
    {
        float divResult = 0.0;
    
        if (b == 0)
        {
            cout << "Error.除法中分母不能为0." << endl;
            exit(1);
        }
        divResult = a / b;
    
        cout << "number1 / number2 = " << divResult << endl;
    }
    
3.7 函数原型
  • 函数使用需要遵循"先声明后使用"原则,在调用函数前需要声明,函数原型声明由函数返回值类型、函数名和参数列表组成,语法如下:

    返回值类型 函数名(参数列表);
    
  • 参数列表由一系列以逗号分隔的参数类型和参数名组成,在函数声明时,参数名可以省略,在函数定义时,形参必须命名,参数列表可以为空,但不能省略,在没有任何形参时可以使用空参数或关键字 v o i d {\rm void} void

  • 函数原型的声明是一个语句,以分号结束;

  • 在函数的定义和声明时,需保证函数原型与函数首部写法一致,即函数返回值类型、函数名、参数个数、参数类型和参数顺序保持一致;

  • 在函数调用时,函数名、实参类型和参数个数应与函数原型一致;

  • 函数定义的位置可在主函数后,亦可在主函数前,如果被调用函数定义在主函数前,则主函数可以直接调用此函数,不必进行声明,如果被调用函数定义在主函数后,则先声明后调用;

  • 函数可以在头文件中声明,在源文件中定义,把声明放在头文件中可以使被调用函数与所有声明保持一致,如果函数的接口发生变化,则只需要修改唯一的声明,在使用时,定义函数源文件需要包含声明该函数的头文件;

  • 实例 ( e x a m p l e 3 _ 5. h 、 e x a m p l e 3 _ 5. c p p 、 e x a m p l e 3 _ 5 _ m a i n . c p p ) ({\rm example3\_5.h、example3\_5.cpp、example3\_5\_main.cpp}) (example3_5.hexample3_5.cppexample3_5_main.cpp)

    // 函数声明
    void func1(char);
    void func2(float);
    void func3(int);
    
    #include <iostream>
    #include "example3_5.h"
    using namespace std;
    
    // 函数定义
    void func1(char c)
    {
        cout << "字符内容为:" << c << endl;
    }
    
    void func2(float f)
    {
        cout << "浮点数内容为:" << f << endl;
    }
    
    void func3(int i)
    {
        cout << "整数内容为:" << i << endl;
    }
    
    #include <iostream>
    #include "example3_5.h"
    using namespace std;
    
    int main()
    {
        // 函数调用
        func1('W');
        func2(3.14);
        func3(520);
    
        return 0;
    }
    
3.8 函数参数
  • C {\rm C} C++中,主函数可以使用函数名和一组由逗号分隔的实参来对函数进行调用,调用的结果是该函数返回值的类型;

  • 在形参被成功初始化后,主函数被挂起,被调用函数开始执行,当被调用函数执行结束后,将被调用函数的返回值传入主函数,主函数继续执行;

  • 定义函数时使用的是形参,函数被调用时使用的是实参,在 C {\rm C} C++中,函数参数传递的方式:值传递、引用传递和指针传递;

  • 值传递:指实参向形参传递的是值,在函数被调用前,形参没有获得内存空间,在函数被调用时,形参才被分配内存单元,然后将实参的值复制到形参中;实参可以是常量、变量和表达式,实参的类型必须和形参类型相同,形参只是复制了实参的值,在被调用函数中形参值的修改不影响实参的值;

  • 函数参数值传递实例 ( e x a m p l e 3 _ 6. c p p ) ({\rm example3\_6.cpp}) (example3_6.cpp)

    /**
     * 作者:罗思维
     * 时间:2023/10/10
     * 描述:函数参数值传递实例。
     */
    #include <iostream>
    using namespace std;
    
    void Swap(int a, int b); // 函数声明;
    
    int main()
    {
        int number1 = 11, number2 = 22;
    
        cout << "number1 = " << number1 << ",number2 = " << number2 << endl;
        Swap(number1, number2); // 函数调用;
        
    	/**
    	* 结果:
    	* number1 = 11,number2 = 22
    	* number1 = 11,number2 = 22
    	*/
        cout << "number1 = " << number1 << ",number2 = " << number2 << endl;
    
        return 0;
    }
    
    // 函数定义,实现两个数的交换;
    void Swap(int a, int b)
    {
        int temp;
        temp = a;
        a = b;
        b = temp;
    }
    
  • m a i n {\rm main} main函数参数。

    // main函数形参定义格式:
    int main(int argc,char *argv[])
    {
        ...
    }
    
    // 参数说明:
    // argv:字符串数组;
    // argc:传递给argv数组的字符串的个数;
    
  • 可变参数长参数:

    // 可变参数长参数定义格式:
    类型标识符 函数名(...);
    类型标识符 函数名(形参1,...);
    
3.9 函数作用域
  • 在函数和类外定义的变量具有全局的作用,称为全局变量, C {\rm C} C++函数体一般包含在一对大括号中,称为语句块,在语句块中定义的变量只具有局部的作用域,即在该函数体中,这些变量称为局部变量,形参是局部变量,局部变量只在其局部的作用域中有效;
  • 变量的生存周期从定义时开始,到退出作用域时销毁,局部变量在作用域内才可以使用它们,作用域外不可以使用这些变量;
  • 主函数中的变量也是局部变量,只在主函数中有效,不能被其他函数使用,主函数也不能使用其他函数的局部变量;
  • 在相同作用域中,变量不可以同名,在不同作用域中,可以使用相同的变量名,它们使用不同的内存,互不干扰;
  • 全局变量定义在函数或类的外面,其作用域从定义位置到文件结束,文件中的所有函数都可以使用全局变量,全局变量遵循"先定义,后使用"原则;
  • 减少使用全局变量:
    • 在程序的整个执行过程中始终占用内存空间;
    • 降低程序的可移植性和可读性;
    • 当与局部变量同名时,全局变量在局部变量作用域中被局部变量屏蔽;
3.10 函数的嵌套与递归调用
  • 函数嵌套:指调用函数时,被调用函数又调用了其他函数,形成嵌套调用关系;

  • 函数嵌套实例 ( e x a m p l e 3 _ 7. c p p ) ({\rm example3\_7.cpp}) (example3_7.cpp)

    /**
     * 作者:罗思维
     * 时间:2023/10/10
     * 描述:函数嵌套实例,计算两个整数的平方差及平方和。
     */
    #include <iostream>
    using namespace std;
    
    int DifferenceOfTwoSquares(int, int);
    int SquareSum(int, int);
    
    int main()
    {
        int number1 = 5, number2 = 3;
    
        cout << "5*5+3*3=" << SquareSum(number1, number2) << endl;
        cout << "5*5-3*3=" << DifferenceOfTwoSquares(number1, number2) << endl;
    
        return 0;
    }
    
    // 定义整数平方函数;
    int Square(int m)
    {
        return m * m;
    }
    
    // 定义平方差函数;
    int DifferenceOfTwoSquares(int a, int b)
    {
        return (Square(a) - Square(b));
    }
    
    // 定义平方和函数;
    int SquareSum(int a, int b)
    {
        return (Square(a) + Square(b));
    }
    
  • 递归调用:指函数直接或间接地调用本身,在使用递归调用时,需要在函数内部设置递归终止条件;

  • 递归调用实例 ( e x a m p l e 3 _ 8. c p p ) ({\rm example3\_8.cpp}) (example3_8.cpp)

    /**
     * 作者:罗思维
     * 时间:2023/10/10
     * 描述:函数递归调用实例,输入一个数,计算其阶乘。
     */
    #include <iostream>
    using namespace std;
    
    int Recursive(int);
    
    int main()
    {
        int number;
        cout << "请输入一个大于等于0的整数:";
        cin >> number;
    
        if (number < 0)
        {
            cout << "输入的整数小于0,输入错误,将退出程序." << endl;
            exit(1);
        }
    
        cout << number << "! = " << Recursive(number) << endl;
    
        return 0;
    }
    
    int Recursive(int n)
    {
        if (n == 0)
        {
            return 1;
        }
        else
        {
            return (n * Recursive(n - 1));
        }
    }
    
3.11 内联函数
  • 内联函数定义格式:

    inline 类型标识符 函数名(参数列表)
    {
        语句序列;
        
        return 返回值类型的值;
    }
    
  • 内联函数在编译时,在调用处用函数体进行替换,没有非内联函数调用时的栈内存的创建和释放开销,节省了参数传递、控制转移等开销;

  • 内联函数实例 ( e x a m p l e 3 _ 9. c p p ) ({\rm example3\_9.cpp}) (example3_9.cpp)

    /**
     * 作者:罗思维
     * 时间:2023/10/10
     * 描述:内联函数实例,输入两个整数,求两个整数之和。
     */
    #include <iostream>
    using namespace std;
    
    // 声明内联函数;
    inline int Sum(int, int);
    
    int main()
    {
        int number1, number2;
    
        cout << "请输入两个整数:";
        cin >> number1 >> number2;
    
        // 调用内联函数;
        cout << "整数之和为:" << Sum(number1, number2) << endl;
    
        return 0;
    }
    
    // 定义求和内联函数;
    inline int Sum(int a, int b)
    {
        return (a + b);
    }
    
  • 内联函数使用注意事项:

    • 内联函数应该简洁,只有几个语句,语句较多时,极大增加程序的代码量;
    • 内联函数体内不能有循环语句、 i f {\rm if} if语句和 s w i t c h {\rm switch} switch语句;
3.12 函数模板
  • 函数模板:指建立一个通用函数,函数中的数据类型不用具体指定,用一个虚拟的类型来代表,这个通用函数就是函数模板;

  • 函数模板定义格式:

    template <typename T>			// T为虚拟的类型名;
    template <class T>
    template <class T1,typename T2>
    
  • 函数模板只适用于函数功能相同、参数个数相同,但类型不同的情况,当函数的参数个数不相同时,不能使用函数模板;

  • 函数模板实例 ( e x a m p l e 3 _ 10. c p p ) ({\rm example3\_10.cpp}) (example3_10.cpp)

    /**
     * 作者:罗思维
     * 时间:2023/10/10
     * 描述:使用函数模板实现简易计算器功能。
     */
    #include <iostream>
    using namespace std;
    
    template <typename T1>
    T1 Sum(T1 a, T1 b)
    {
        return (a + b);
    }
    
    template <typename T2>
    T2 Sub(T2 a, T2 b)
    {
        return (a - b);
    }
    
    template <typename T3>
    T3 Mul(T3 a, T3 b)
    {
        return (a * b);
    }
    
    template <typename T4>
    T4 Div(T4 a, T4 b)
    {
        return (a / b);
    }
    
    int main()
    {
        int iNumber1, iNumber2;
        float fNumber1, fNumber2;
    
        cout << "请依次输入两个整数和两个浮点数:";
        cin >> iNumber1 >> iNumber2 >> fNumber1 >> fNumber2;
    
        cout << "iNumber1 + iNumber2 = " << Sum(iNumber1, iNumber2) << endl;
        cout << "fNumber1 + fNumber2 = " << Sum(fNumber1, fNumber2) << endl;
        cout << "===============================" << endl;
    
        cout << "iNumber1 - iNumber2 = " << Sub(iNumber1, iNumber2) << endl;
        cout << "fNumber1 - fNumber2 = " << Sub(fNumber1, fNumber2) << endl;
        cout << "===============================" << endl;
    
        cout << "iNumber1 * iNumber2 = " << Mul(iNumber1, iNumber2) << endl;
        cout << "fNumber1 * fNumber2 = " << Mul(fNumber1, fNumber2) << endl;
        cout << "===============================" << endl;
    
        if ((iNumber2 != 0) && (fNumber2 != 0))
        {
            cout << "iNumber1 / iNumber2 = " << Div(iNumber1, iNumber2) << endl;
            cout << "fNumber1 / fNumber2 = " << Div(fNumber1, fNumber2) << endl;
        }
        else
        {
            cout << "iNumber2或fNumber2分母为0." << endl;
        }
    
        return 0;
    }
    
3.13 实战2

项目需求:提示用户从键盘输入两个整数,求这两个数的最大公约数和最小公倍数。

代码实现 ( p r o j e c t 3 _ 2. c p p ) ({\rm project3\_2.cpp}) (project3_2.cpp)

/**
 * 作者:罗思维
 * 时间:2023/10/10
 * 描述:提示用户从键盘输入两个整数,求这两个整数的最大公约数和最小公倍数。
 */
#include <iostream>
using namespace std;

int gcd(int, int);
int lcm(int, int);

int main()
{
    int iNumber1, iNumber2;

    cout << "请输入两个非负整数:";
    cin >> iNumber1 >> iNumber2;

    cout << "两个整数最大公约数为:" << gcd(iNumber1, iNumber2) << endl;
    cout << "两个整数最小公倍数为:" << lcm(iNumber1, iNumber2) << endl;

    return 0;
}

// 计算最大公约数;
int gcd(int m, int n)
{
    if (m > n)
    {
        swap(m, n);
    }
    while (n > 0)
    {
        int r = m % n;
        m = n;
        n = r;
    }
    return m;
}

// 计算最小公倍数;
int lcm(int m, int n)
{
    return (m * n / gcd(m, n));
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/438106.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于iOS真机的Appium自动化测试

必要条件 XCode > 6.0, 7.1.1&#xff08;注意Appium并不一定支持最新版本的Xcode&#xff09;Mac OS X 10.10 or 更高, 建议使用10.11.1 Xcode 安装 APP Store安装 注意事项&#xff1a; Xcode 安装包很大&#xff08;5G左右&#xff09;&#xff0c;Xcode移动到应用程序…

2024年腾讯云学生服务器优惠活动「云+校园」政策解读

2024年腾讯云学生服务器优惠活动「云校园」&#xff0c;学生服务器优惠价格&#xff1a;轻量应用服务器2核2G学生价30元3个月、58元6个月、112元一年&#xff0c;轻量应用服务器4核8G配置191.1元3个月、352.8元6个月、646.8元一年&#xff0c;CVM云服务器2核4G配置842.4元一年&…

linux命令行或桌面 显卡压力测试

windows下的压力测试非常简单&#xff0c;有很多图形化的测试工具 在github上找到一个项目&#xff1a;github链接 1.下载工具 cd /usr/localgit clone https://github.com/wilicc/gpu-burn如果没有安装git&#xff0c;则先安装 apt-get install git2.安装 cd /usr/local/…

Linux/Validation

Enumeration nmap 第一次扫描发现系统对外开放了22&#xff0c;80&#xff0c;4566和8080端口&#xff0c;端口详细信息如下 系统对外开放了4个端口&#xff0c;从nmap的结果来看&#xff0c;8080无法访问&#xff0c;手动尝试后4566也无法访问&#xff0c;只能从80端口开始 …

晶圆上特性表征

测试仪器&#xff1a; 半导体器件表征系统&#xff08;DC&CV&#xff09;&#xff1a;Keysight B1500A 半导体器件分析仪&#xff08;B1500A&#xff09;测量能力&#xff1a; 1.IV、CV、脉冲/动态IV范围为0.1 fA-1 A/0.5 uV-200 V 2.器件、材料、半导体、有源/无源元件的…

华为数通方向HCIP-DataCom H12-821题库(多选题:41-60)

第41题 BGP OPEN消息中携带如下哪些信息? A、路由属性 B、BGP Router ID C、Hold time D、本地自治系统(AS)号 【参考答案】BCD 【答案解析】 B. BGP Router ID:OPEN消息中包含发送方BGP路由器的Router ID,用于唯一标识BGP路由器。C.Hold time:OPEN消息中包含发送方BGP路由…

Java多线程——如何保证原子性

目录 引出原子性保障原子性CAS 创建线程有几种方式&#xff1f;方式1&#xff1a;继承Thread创建线程方式2&#xff1a;通过Runnable方式3&#xff1a;通过Callable创建线程方式4&#xff1a;通过线程池概述ThreadPoolExecutor API代码实现源码分析工作原理&#xff1a;线程池的…

牛客每日一题之 前缀和

目录 题目介绍&#xff1a; 算法原理&#xff1a; 前缀和&#xff1a; 代码实现&#xff1a; 题目介绍&#xff1a; 题目链接&#xff1a;【模板】前缀和_牛客题霸_牛客网 算法原理&#xff1a; 先讲讲暴力解法每次求出数组下标r之前元素的和&#xff0c;再减去数组下标l-…

pycuda安装失败问题

pycuda安装失败问题 遇到一个pycuda安装失败的问题&#xff0c; 这里有一个合理的解释可以去尝试一下&#xff0c;看起来很有道理&#xff1a;

2024.3.7 FreeRTOS 作业

思维导图 练习题 1.使用ADC采样光敏电阻数值&#xff0c;如何根据这个数值调节LED灯亮度。 //打开定时器3的通道3&#xff0c;并且设置为PWM功能HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1…

基于springboot+vue的旅游管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

国产蓝鹏测控测径仪如何?

随着国力增强&#xff0c;中国制造品质提升&#xff0c;不仅仅是国外更多人认可&#xff0c;国内对国产制品也接受良好&#xff0c;测径仪这种智能测量设备&#xff0c;很多国内外厂家也在用国产设备。 测径仪厂家 蓝鹏测控作为智能几何尺寸测量仪生产厂家&#xff0c;已有10多…

使用Kali搭建钓鱼网站教程

一、前言 使用kali工具一分钟制作出和目标网站一模一样的钓鱼网站。目标用户使用钓鱼网站登录自己的账号&#xff0c;账号密码将被自动劫持。 二、钓鱼网站的制作过程 1.在虚拟机VMvare中登录kali linux 2.准备一个目标网址 3.在kail中搜索使用工具 4.在弹出的选项中选择第一…

文心一言眼中的ChatGPT是什么样的

Q: 你好文心一言&#xff0c;请说一说你眼中的chatgpt A: 在我眼中&#xff0c;ChatGPT是一种非常先进和强大的自然语言处理模型&#xff0c;它展示了人工智能技术的显著进步。ChatGPT拥有出色的语言理解和生成能力&#xff0c;能够与用户进行流畅、自然的对话&#xff0c;并尝…

大数据背景下R语言lavaan在SEM中的高效应用

结构方程模型&#xff08;SEM&#xff09;是揭示系统内变量间复杂关系的强大工具。它利用图形化的方式&#xff0c;将多变量间的因果关系网展现得淋漓尽致&#xff0c;具备出色的数据分析能力和广泛的适用性。近年来&#xff0c;无论是在生态、进化、环境领域&#xff0c;还是在…

机器学习-面经(part8、贝叶斯和其他知识点)

机器学习面经其他系列 机器学习面经系列的其他部分如下所示&#xff1a; 机器学习-面经(part1)-初步说明 机器学习-面经(part2)-交叉验证、超参数优化、评价指标等内容 机器学习-面经(part3)-正则化、特征工程面试问题与解答合集机器学习-面经(part4)-决策树共5000字的面试问…

嵌入式驱动学习第二周——Linux休眠唤醒

前言 这篇博客来聊一聊Linux系统的休眠与唤醒。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程&#xff0c;未来预计四个月将高强度更新本专栏&#xff0c;喜欢的可以关注本博主并订阅本专栏&#xff0c;一起讨论一起学习。现在关注就是老粉啦&#xff01; 目录 前言1. …

爬虫实战——麻省理工学院新闻

文章目录 发现宝藏一、 目标二、 浅析三、获取所有模块四、请求处理模块、版面、文章1. 分析切换页面的参数传递2. 获取共有多少页标签并遍历版面3.解析版面并保存版面信息4. 解析文章列表和文章5. 清洗文章6. 保存文章图片 五、完整代码六、效果展示 发现宝藏 前些天发现了一…

Eclipse左边project框如何打开?

1、点击Eclipse顶端window 2、点击Show View 3、点击Project Explorer。 如下图&#xff08;图片转自其他博主&#xff09;。

Web自动化测试--selenium

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…