- 函数与结构体
- 函数
- 什么是函数
- 函数的声明
- 函数的定义
- 函数的调用
- 参数传递:传值和引用
- 参数传递:数组参数
- 参数传递:参数默认值
- 递归函数
- 递归函数的两个基本要素
- 递归函数的写法
- 结构体
- 什么是结构体
- 结构体的定义
- 结构体变量声明
- 初始化结构体
- 结构体成员访问
- 结构体作为函数参数
- 代码:员工信息的存储
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; }
调用函数时,参数的传递一般分为传值传递和引用传递
- 传值传递
- 把参数的实际值赋值给函数的形式参数
- 修改函数内的形式参数对实际参数没有影响
#includeusing 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; }
#includeusing 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; }



