栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++语法基础(6)——函数与结构体

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++语法基础(6)——函数与结构体

文章目录
  • 函数与结构体
    • 函数
      • 什么是函数
      • 函数的声明
      • 函数的定义
      • 函数的调用
      • 参数传递:传值和引用
      • 参数传递:数组参数
      • 参数传递:参数默认值
    • 递归函数
      • 递归函数的两个基本要素
      • 递归函数的写法
    • 结构体
      • 什么是结构体
      • 结构体的定义
      • 结构体变量声明
      • 初始化结构体
      • 结构体成员访问
      • 结构体作为函数参数
      • 代码:员工信息的存储

函数与结构体 函数 什么是函数

C++中变量需要声明,告诉程序有这么一个变量。同理,函数也应该在调用前进行声明,告诉编译器函数名称及如何调用函数。
声明后的函数主要可以分为定义与调用两个部分,以菜谱为例:

  • 函数的定义:“炒蛋”的具体步骤说明。
  • 函数的调用:在“番茄炒蛋”中“炒蛋”,或在“蒜苔炒蛋”中“炒蛋”。

一个C++程序无论包含多少个函数,必须有一个主要的函数,叫做main()函数,作为执行整个程序的入口。你可以在main()函数中去调用其他函数,同样地,其它函数之间也可以互相调用。

  • 实参的个数即函数设定的传入参数个数
函数的声明
  • 函数的声明是为了告诉编译器如何调用这个函数,形式如下:
  • 返回值类型 函数名(参数1类型 参数1, 参数2类型 参数2, ..., 参数n类型 参数n);
  • 有些函数执行所需的操作而不返回任何值,此时的返回值类型是void
int MyMax(int a, int b);
函数的定义
  • C++中定义函数时,需要在声明的基础上写好函数体,函数定义的形式如下:
返回值类型 函数名(参数1类型 参数1, 参数2类型 参数2, ..., 参数n类型 参数n) {
    函数体
}
// 声明这个函数
int MyMax(int a, int b);

// 定义这个函数,输入为a和b两个整型
int MyMax(int a, int b) {
    int max_num;
    
    if (a>b)
        max_num = a;
    else
        max_num = b;
    
    // 返回a和b两个数中更大的一个
    return max_num;
}
函数的调用

C++中,定义了函数之后,函数里面的代码是不会执行的,只有调用了这个函数,才会去执行函数中的代码

Tips:如果我们函数的定义在调用前进行的话,也可以省略函数的声明这一步。

#include 
using namespace std;

// 定义这个函数,在调用前就定义了,所以可以省略声明
int MyMax(int a, int b) {
    int max_num;
    if (a > b)
        max_num = a;
    else
        max_num = b;
    return max_num;
}

int main() {
    int num1 = 30;
    int num2 = 50;
    // 变量 num3 表示这两个数字中更大的值
    int num3;
    
    // 调用
    num3 = MyMax(num1, num2);
    
    cout << num3 << endl;
    return 0;
}
参数传递:传值和引用

调用函数时,参数的传递一般分为传值传递和引用传递

  • 传值传递
    • 把参数的实际值赋值给函数的形式参数
    • 修改函数内的形式参数对实际参数没有影响
#include 
using namespace std;

// 传值传递
void swap1(int x, int y) {
    cout << "传值传递:" << endl;
    cout << "交换前,x 的值:" << x << endl;
    cout << "交换前,y 的值:" << y << endl;
    
    int temp;
    temp = x; 
    x = y;    
    y = temp; 

    cout << "交换后,x 的值:" << x << endl;
    cout << "交换后,y 的值:" << y << endl;

    return;
}

int main () {
    // 局部变量声明
    int a = 100;
    int b = 200;

    cout << "交换前,a 的值:" << a << endl;
    cout << "交换前,b 的值:" << b << endl;

    // 调用传值传递的函数来交换值
    swap1(a, b);

    cout << "传值传递交换后,a 的值:" << a << endl;
    cout << "传值传递交换后,b 的值:" << b << endl;

    return 0;
}
  • 引用传递
    • 该方法把参数的引用赋值给形式参数
    • 函数内通过会引用访问实际参数,若进行修改会改变实际参数的值

Tips:在引用传递过程中,被调函数的形式参数虽然也作为局部变量开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。

#include 
using namespace std;

// 引用传递
void swap2(int &x, int &y) {
    cout << "引用传递:" << endl;
    cout << "交换前,x 的值:" << x << endl;
    cout << "交换前,y 的值:" << y << endl;

    int temp;
    temp = x; 
    x = y;    
    y = temp; 

    cout << "交换后,x 的值:" << x << endl;
    cout << "交换后,y 的值:" << y << endl;
  
    return;
}

int main () {
    // 局部变量声明
    int a = 100;
    int b = 200;

    cout << "交换前,a 的值:" << a << endl;
    cout << "交换前,b 的值:" << b << endl;

    // 调用引用传递的函数来交换值
    swap2(a, b);

    cout << "引用传递交换后,a 的值:" << a << endl;
    cout << "引用传递交换后,b 的值:" << b << endl;

    return 0;
}
参数传递:数组参数
  • 数组名表示的是数组的地址,所以这时候我们传递的参数实际上是数组的地址。
    • 在函数中修改数组里的某一个值,会在内存中直接修改这个数组。

举例:返回数组中最大的一个值

int MyMax(int a[], int len) {
    int max_num = 0;
    for (int i=0; i
        if (a[i] > max_num)
            max_num = a[i];
    }
    return max_num;
}

int main() {
    int nums[10] = {3, 2, 1, 1, 2, 3, 3, 2, 1, 0};
    cout << MyMax(nums, 10) << endl;
}
参数传递:参数默认值
  • 函数定义时,我们可以给函数的参数设置默认值
    • 这样我们调用函数时,可以选择不传递参数,选择默认的参数。
// 定义这个函数,在调用前就定义了,所以可以省略声明
int MyMax(int a, int b = 100) {
    int max_num;
    if (a>b)
        max_num = a;
    else
        max_num = b;
    return max_num;
}
  • 在调用函数时,如果只传递一个参数a,比如MyMax(30),函数就会默认b的值为100,效果等同于MyMax(30, 100)。
  • 如果调用函数时,还是传递了两个参数,比如MyMax(30, 80),那么就不使用b的默认值。

Tips:若给某一参数设置了默认值,那么在参数列表中,位于该参数之后的所有参数都必须也设置默认值。

递归函数

函数的函数体中又调用了它自己,这就叫做“递归函数”。

递归函数的两个基本要素
  • 递归关系
    • 问题规模为n时与问题规模为n-1时之间的转换关系
    • 计算某个数字的阶乘,递归的关系就是:数字n的阶乘 = 数字n * 数字n-1的阶乘
    • 这个函数可以写成: 递归关系的程序段
int factorial(int n) {
    return n * factorial(n-1);
}
  • 递归的终止条件
    • 递归关系需要有一个递归终止的条件。
    • 在计算阶乘中,递归终止的条件是计算到数字1的阶乘的时候,函数可以直接返回数字1的阶乘就是1
    • 补充上这个条件: 递归终止条件的程序段
int factorial(int n) {
    if (n == 1)
        return 1;
    else
        return n * factorial(n-1);
}

Tips:更严谨的,我们可以在n小于1的时候,输出错误操作。

递归函数的写法

计算数字阶乘的程序段

#include 
using namespace std;

int factorial(int n) {
    if (n < 1) {
        cout << "错误操作" << endl;
        return -1;
    }

    if (n == 1)
        return 1;
    else
        return n * factorial(n-1);
}

int main() {
    cout << factorial(4) << endl;
    return 0;
}

结构体
  • 因为内存对齐的存在,结构体类型的变量的字节数不等于各成员字节数之和。
什么是结构体

在C++中,我们可以使用结构体来将一组不同类型的数据聚合成一个整体

结构体的定义
  • 结构体有很多个不同类型的变量,用于表示这个结构体的属性,称之为结构体的成员变量。
  • 在使用结构体之前,我们需要在代码中定义结构体,定义方式如下:
struct 结构体名称 {
    数据类型1 变量名1;
    数据类型2 变量名2, 变量名3;
    ...
    数据类型n 变量名m;
};
struct Student{    
    int number, birth_year;
    string name;
};
结构体变量声明
  • 定义结构体之后,我们就可以声明结构体类型的变量,作为结构体的实例。
  • 声明结构体变量,每个变量都包含具有相同名称的成员变量。
struct Student{    
    int number, birth_year;
    string name;
};

// 声明三个学生
Student zhang_san, li_si, wang_mazi;
// 声明一个学生数组,数组长度为500,可以保存500个学生的信息
Student students[500];
  • 另一种声明结构体变量的方式是:直接在定义结构体时,声明结构体变量。
struct Student{    
    int number, birth_year;
    string name;
} zhang_san, li_si, wang_mazi;

struct Student{    
    int number, birth_year;
    string name;
} students[500];
初始化结构体

对于结构体变量,可以通过两种方式初始化它:使用初始化列表或构造函数。

  • 使用初始化列表和数组的初始化类似,会根据给出的元素依次初始化结构体中的每个成员
    • 如果给出的元素小于成员数量,排在后面的就会保持没有被初始化
struct Student{    
    int number, birth_year;
    string name;
};

// 初始化一个学号为1,2000年出生,名叫 ZhangSan的学生
Student zhang_san = {1, 2000, "ZhangSan"};
  • 采用构造函数初始化,可以在创建一个结构体变量而不向其传递某些成员变量的值时,提供默认值
    • 可以先在结构体内部完成一个构造函数,再调用这个构造函数来初始化结构体变量
struct Student{    
    int number, birth_year;
    string name;
    
    // 在结构体里定义构造函数
    // 在初始化时所有学生的出生年份都被设置为2000
    // 可以传入两个参数,分别代表学号和姓名,如果不传入参数,默认学号为0,姓名为""
    Student (int num=0, string n="") {
        number = num;
        birth_year = 2000;
        name = n;
    }
};

// 初始化时只用传递两个参数即可
Student li_si(2, "LiSi");
结构体成员访问
  • 要访问某一个结构体变量的某个成员,可以使用结构体变量名.结构体成员变量名的方式访问:
cout << zhang_san.number << endl;
cout << zhang_san.name << endl;
cout << li_si.birth_year << endl;
结构体作为函数参数

结构体变量也可以通过传值传递和引用传递给函数。

  • 传值传递意味着需要生成整个原始结构的副本并传递给函数。

Tips:因为不希望浪费时间和空间来复制整个结构体,所以传值传递一般在结构很小时采用。

  • 引用传递意味着函数可以访问原始结构的成员变量,从而可能更改它们
    • 如果不想让函数更改任何成员变量值,那么可以将结构体变量作为一个常量引用传递给函数
    • 常量引用传递需要在参数类型前加上const关键字。
#include 
using namespace std;

struct Student{    
    int number, birth_year;
    string name;
};

// TODO 完成该函数,展示学生的学号、姓名和出生年份
void showStudent(const Student &student_info) {
    cout << "Student Number : " << student_info.number << endl;
    cout << "Name : " << student_info.name << endl;
    cout << "Birth Year : " << student_info.birth_year << endl;
}

int main() {
    Student zhang_san = {1, 2000, "ZhangSan"};
    
    // 调用函数
    showStudent(zhang_san);
    return 0;
}
代码:员工信息的存储
#include 
using namespace std;

// TODO 定义结构体 Employee,并声明长度为5的结构体数组 employees_info
struct Employee{
    int number, working_hours;
    string name;

    // 构建函数
    Employee (int num=0, string n="") {
        number = num;
        working_hours =8;
        name = n;
    }
} employees_info[5];

// TODO 完成展示某位员工信息的函数
void showEmployee(const Employee &employees_info) {
    cout << "Employee Number : " << employees_info.number << endl;
    cout << "Name : " << employees_info.name << endl;
    cout << "Working Hours : " << employees_info.working_hours << endl;
}

int main() {
    // TODO 初始化5位员工
    employees_info[0] = Employee(1, "XiaoYi");
    employees_info[1] = Employee(2, "XiaoEr");
    employees_info[2] = Employee(3, "XiaoLiu");
    employees_info[3] = Employee(4, "XiaoSi");
    employees_info[4] = Employee(5, "XiaoWu");
    
    
    // TODO 调用函数展示5位的信息
    for(int i=0; i<5; i++) {
        showEmployee(employees_info[i]);
    }
    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1000677.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号