函数
6.1 函数的定义与使用
函数是C++中非常重要的概念,通过函数我们可以将一个大的任务分解成若干个小的可复用的模块,从而提高代码的可读性和可维护性。
6.1.1 函数的定义
函数的定义包括函数的返回类型、函数名、参数列表和函数体。下面是一个求两个整数中较大值的函数的例子:
【例6-1】求两个整数中较大值的函数
#include <iostream>
using namespace std;
int max(int a, int b)
{
return (a > b) ? a : b;
}
int main()
{
int num1 = 10, num2 = 20;
int result = max(num1, num2);
cout << "较大值为:" << result << endl;
return 0;
}
代码解析:
- 函数
max
接受两个整数参数a
和b
,并返回较大值。 - 在主函数
main
中,我们定义了两个整数变量num1
和num2
,然后调用函数max
求解较大值,并将结果赋给result
变量。 - 最后,我们输出
result
的值,即较大值。
6.1.2 函数的声明与调用
有时候我们需要在使用一个函数之前提前声明该函数,以便让编译器知道函数的存在。下面是一个求x的n次方的函数的例子:
【例6-2】编写一个求x的n次方的函数
#include <iostream>
using namespace std;
int power(int x, int n); // 函数声明
int main()
{
int x, n;
cout << "请输入x和n的值:";
cin >> x >> n;
int result = power(x, n); // 函数调用
cout << x << "的" << n << "次方为:" << result << endl;
return 0;
}
int power(int x, int n) { // 函数定义
int result = 1;
for (int i = 0; i < n; i++)
{
result *= x;
}
return result;
}
代码解析:
- 首先在函数
main
之前,我们声明了一个函数power
,用于计算x的n次方。 - 在主函数
main
中,我们先从用户输入获取x和n的值。 - 接下来,我们调用函数
power(x, n)
求解x的n次方,并将结果赋给result
变量。 - 最后,我们输出
result
的值,即x的n次方。
6.2 函数的参数传递
函数的参数传递方式有多种,包括数值传递、指针传递、引用传递、数组传递和字符指针传递。
6.2.1 数值作为函数的参数
数值作为函数的参数时,函数对参数的改变不会影响到原始值。下面是一个交换两个变量值的函数的例子:
【例6-3】写一个函数,交换主函数中两个变量的值
#include <iostream>
using namespace std;
void swapValues(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int num1 = 10, num2 = 20;
cout << "交换前:" << endl;
cout << "num1 = " << num1 << ", num2 = " << num2 << endl;
swapValues(num1, num2);
cout << "交换后:" << endl;
cout << "num1 = " << num1 << ", num2 = " << num2 << endl;
return 0;
}
代码解析:
- 在函数
swapValues
中,我们定义了一个临时变量temp
来保存变量a的值。然后我们将变量a的值赋给变量b,将变量b的值赋给变量a,最后将临时变量temp
的值赋给变量b。 - 在主函数
main
中,我们定义了两个整数变量num1
和num2
并赋初值。首先输出交换前的值,然后调用函数swapValues(num1, num2)
进行交换,再输出交换后的值。 - 结果显示,变量
num1
和num2
的值并没有交换,表明数值作为参数传递时函数对参数的改变不影响原始值。
6.2.2 指针作为函数的参数
指针作为函数的参数能够改变指针所指向的变量的值。下面是一个交换两个变量值的函数的例子:
【例6-4】指针作为函数的参数,交换主调函数中两个变量的值
#include <iostream>
using namespace std;
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int x = 10;
int y = 20;
cout << "Before swap: x = " << x << ", y = " << y << endl;
swap(&x, &y);
cout << "After swap: x = " << x << ", y = " << y << endl;
return 0;
}
此例子中定义了一个名为swap
的函数,接受两个整数指针作为参数,并通过指针来交换它们所指向的值。在主函数中,创建了两个整数变量x
和y
,并打印它们的值。然后调用swap函数,传递x和y的地址作为参数。此时,在swap
函数中的交换操作会直接修改主函数中x
和y
的值,因为传递了它们的地址。
6.2.3 引用作为函数的参数
【例6-5】引用的使用
#include <iostream>
using namespace std;
void increment(int &a)
{
a++;
}
int main()
{
int x = 10;
cout << "Before increment: x = " << x << endl;
increment(x);
cout << "After increment: x = " << x << endl;
return 0;
}
此例子中定义了一个名为increment
的函数,接受一个整数引用作为参数,并将其值增加1
。在主函数中,创建了一个整数变量x
,并打印它的值。然后调用increment
函数,传递x
的引用作为参数。因为引用在参数传递中相当于原变量的别名,所以对引用的操作会直接修改原变量的值。
【例6-6】引用作为函数的参数,交换主调函数中两个变量的值
#include <iostream>
using namespace std;
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int x = 10;
int y = 20;
cout << "Before swap: x = " << x << ", y = " << y << endl;
swap(x, y);
cout << "After swap: x = " << x << ", y = " << y << endl;
return 0;
}
此例子中定义了一个名为swap
的函数,接受两个整数引用作为参数,并通过引用来交换它们的值。在主函数中,创建了两个整数变量x
和y
,并打印它们的值。然后调用swap
函数,传递x
和y
的引用作为参数。此时,在swap
函数中的交换操作会直接修改主函数中x
和y
的值,因为引用在参数传递中相当于原变量的别名。
【例6-7】两个计算圆面积的函数
#include <iostream>
using namespace std;
void calculateArea(const double &radius, double &area)
{
area = 3.14 * radius * radius;
}
int main()
{
double r = 5.0;
double a = 0.0;
calculateArea(r, a);
cout << "The area is: " << a << endl;
return 0;
}
此例子中定义了一个名为calculateArea
的函数,接受一个常量双精度引用radius
和一个双精度引用area
作为参数,并根据给定的半径计算面积赋值给area
。在主函数中,创建了一个双精度变量r
和a
,并通过调用calculateArea
函数来计算圆的面积,并将结果保存在a
变量中,最后打印出面积值。
6.2.4 数组作为函数的参数
【例6-8】将数组中的元素按相反的顺序存放
#include <iostream>
using namespace std;
void reverseArray(int arr[], int size)
{
int start = 0;
int end = size - 1;
while (start < end)
{
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
int main()
{
int arr[] = {1, 2, 3, 4, 5};
int size = sizeof(arr) / sizeof(arr[0]);
cout << "Before reverse: ";
for (int i = 0; i < size; i++)
{
cout << arr[i] << " ";
}
cout << endl;
reverseArray(arr, size);
cout << "After reverse: ";
for (int i = 0; i < size; i++)
{
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
此例子中定义了一个名为reverseArray
的函数,接受一个整型数组和数组大小作为参数,并将数组中的元素按相反的顺序存放。在主函数中,创建了一个整型数组arr
,并通过sizeof
运算符计算出数组的大小。然后,打印出原数组的元素值,并调用reverseArray
函数来对数组进行翻转操作,最后再次打印出翻转后的数组。
6.2.5 字符指针作为函数参数
【例6-9】连续两个字符串的函数
#include <iostream>
#include <cstring>
using namespace std;
void concatenate(const char *str1, const char *str2, char *result)
{
strcpy(result, str1);
strcat(result, str2);
}
int main()
{
char str1[] = "Hello, ";
char str2[] = "World!";
char result[100];
concatenate(str1, str2, result);
cout << "Concatenated string: " << result << endl;
return 0;
}
此例子中定义了一个名为concatenate
的函数,接受两个常量字符指针str1
和str2
以及一个字符指针result
作为参数,并将str1
和str2
连接起来存放到result
中。在主函数中,创建了两个字符数组str1
和str2
,以及一个足够大的字符数组result
来存放连接后的结果。然后,调用concatenate
函数,传递str1
、str2
和result
的地址作为参数,并打印出连接后的字符串。
6.3 函数的嵌套调用与递归调用
6.3.1 函数的嵌套调用
函数的嵌套调用是指在一个函数中调用了另一个函数。通过函数的嵌套调用,我们可以将复杂的问题拆解成多个简单的子问题,提高代码的可读性和复用性。下面是一个示例。
【例6-10】计算1!+2!+3!+…+n!。
#include <iostream>
using namespace std;
int factorial(int n)
{
int result = 1;
for (int i = 1; i <= n; i++)
{
result *= i;
}
return result;
}
int sumFactorials(int n)
{
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += factorial(i);
}
return sum;
}
int main()
{
int n;
cout << "Enter a positive integer: ";
cin >> n;
cout << "Sum of factorials up to " << n << " is: " << sumFactorials(n) << endl;
return 0;
}
在上面的代码中,我们定义了两个函数factorial
和sumFactorials
。factorial
函数用来计算给定数的阶乘,sumFactorials
函数则调用了factorial
函数来计算1到n的阶乘之和。在main
函数中,我们通过用户输入得到一个正整数n,然后调用sumFactorials
函数来计算并输出结果。
6.3.2 函数的递归调用
函数的递归调用是指函数自己调用自己。通过递归调用,我们可以解决一些需要重复执行相同操作的问题,比如计算阶乘、解决Hanoi塔问题等。下面是两个例子,一个用递归的方法求n的阶乘,另一个是解决Hanoi塔问题。
【例6-11】用递归的方法求n的阶乘
#include <iostream>
using namespace std;
int factorial(int n)
{
if (n == 0)
{
return 1;
} else
{
return n * factorial(n - 1);
}
}
int main()
{
int n;
cout << "Enter a non-negative integer: ";
cin >> n;
cout << "Factorial of " << n << " is: " << factorial(n) << endl;
return 0;
}
以上代码中,factorial
函数用递归的方式计算n的阶乘。当n为0时,递归结束,直接返回1;否则,返回n与factorial(n - 1)
的乘积。在main
函数中,我们通过用户输入得到一个非负整数n,然后调用factorial
函数来计算并输出结果。
【例6-12】Hanoi 塔问题
#include <iostream>
using namespace std;
void hanoi(int n, char src, char dst, char aux)
{
if (n == 1)
{
cout << "Move disk 1 from " << src << " to " << dst << endl;
return;
}
else
{
hanoi(n - 1, src, aux, dst);
cout << "Move disk " << n << " from " << src << " to " << dst << endl;
hanoi(n - 1, aux, dst, src);
}
}
int main()
{
int n;
cout << "Enter the number of disks: ";
cin >> n;
hanoi(n, 'A', 'C', 'B');
return 0;
}
在上面的代码中,hanoi
函数用递归的方式解决Hanoi塔问题。当n为1时,直接将盘子从源柱移动到目标柱;否则,先将上面的n-1个盘子从源柱通过辅助柱移动到目标柱,再将第n个盘子从源柱直接移动到目标柱,最后将n-1个盘子从辅助柱通过源柱移动到目标柱。在main
函数中,我们通过用户输入得到塔的层数n,然后调用hanoi
函数来求解并输出每个移动步骤。