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函数来求解并输出每个移动步骤。