从零开始的cpp学习(六)
函数
一个典型的函数定义包括:返回类型、函数名称、由任意个参数组成的列表以及函数体与返回值。
使用函数时只需写函数名,并在括号里给每个参数赋值。
例:使用函数求阶乘
1 |
|
函数的参数
形参和实参
实参是形参的初始值。实参是调用时的,形参是定义时的。形参和实参的个数必须匹配。当传入的实参个数少于形参个数时,没有被传入值的形参会使用默认值。
1 | foo("hello"); // 错误:实参类型不正确 |
函数的形参列表
1 | int f1(int v1, v2) {/* … */} // 错误 |
如果没有形参可以不写列表,也可以在()
里写void
。
1 | void f1() {/* …. */} // 隐式地定义空形参列表 |
返回类型
大多数类型都能用作函数的返回类型。一种特殊的返回类型是void
,它表示函数不返回任何值。函数的返回类型不能是数组类型或函数类型,但可以是指向数组或者函数的指针。
局部变量、全局变量与静态变量
局部变量只可以在函数内部使用,全局变量可以在所有函数内使用。当局部变量与全局变量重名时,会优先使用局部变量。
静态变量的初始化只会在第一次调用时被执行,相当于在函数内部的一个只有该函数能用的全局变量。可以用来统计一个函数被调用了多少次。
1 |
|
输入
1 | 3 |
输出
1 | call 1 times |
参数传递
传值参数
当初始化一个非引用类型的变量时,初始值被拷贝给变量。此时,对变量的改动不会影响初始值。
编写函数,输入两个数返回更大的那一个
1 |
|
输入
1 | 3 7 |
输出
1 | 7 |
在max()
函数内重新定义变量值,此时对主函数内a、b无影响
1 |
|
输入
1 | 3 7 |
输出
1 | 20 |
传引用参数
当函数的形参为引用类型时,对形参的修改会影响实参的值。使用引用的作用:避免拷贝、让函数返回额外信息。
比如,如果在写在max()
的形参列表时使用&
引用并在函数内部改变形参的值,则会改变主函数里实参的值。
1 |
|
输入
1 | 3 7 |
输出
1 | 20 |
数组形参
一维数组形参写法:
1 | void print(int *a) {/* … */} |
使用例
1 |
|
多维数组写法:
1 | // 多维数组中,除了第一维之外,其余维度的大小必须指定 |
使用例
1 |
|
在函数中对数组中的值的修改,会影响函数外面的数组。
1 |
|
输出
1 | 1 2 3 |
返回类型和return语句
无返回值函数
没有返回值的return;
语句只能用在返回类型是void
的函数中。返回void
的函数不要求非得有return;
语句,因为在这类函数的最后一句后面会隐式地执行return
。
通常情况下,void
函数如果想在它的中间位置提前退出,可以使用return
语句。return
的这种用法有点类似于我们用break
语句退出循环。
有返回值的函数
只要函数的返回类型不是void
,则该函数内的每条return
语句必须返回一个值。return
语句返回值的类型必须与函数的返回类型相同,或者能隐式地转换函数的返回类型。
函数递归
求1~5的阶乘
1 |
|
例题
n的阶乘
输入一个整数 n,请你编写一个函数,
int fact(int n)
,计算并输出 n 的阶乘输入格式
共一行,包含一个整数 n。
输出格式
共一行,包含一个整数表示 n 的阶乘的值。
输入样例
1
3
输出样例
1
6
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using namespace std;
int fact(int n)
{
int ans = 1;
for (int i = 1; i <= n; i ++ )
ans *= i;
return ans;
}
int main()
{
int n;
cin >> n;
cout << fact(n) << endl;
return 0;
}x和y的最大值
输入两个整数 x 和 y,请你编写一个函数,
int max(int x, int y)
,计算并输出 x 和 y 的最大值。输入格式
共一行,包含两个整数 x 和 y。
输出格式
共一行,包含一个整数,表示两个数中较大的那个数。
输入样例
1
3 6
输出样例
1
6
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using namespace std;
int max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
int a, b;
cin >> a >> b;
cout << max(a, b) << endl;
return 0;
}最大公约数
输入两个整数 a 和 b,请你编写一个函数,
int gcd(int a, int b)
, 计算并输出 a 和 b 的最大公约数。输入格式
共一行,包含两个整数 a 和 b。
输出格式
共一行,包含一个整数,表示 a 和 b 的最大公约数。
输入样例
1
12 16
输出样例
1
4
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using namespace std;
int gcd(int n, int m)
{
for (int i = m; i >= 1; i --)
{
if (m % i == 0 && n % i == 0)
return i;
}
}
int main()
{
int a, b;
cin >> a >> b;
if (a < b)
swap(a, b);
cout << gcd(a, b) << endl;
return 0;
}交换数值
输入两个整数 x 和 y,请你编写一个函数, 交换两个整数的数值并输出交换后的 x 和 y。
格式为:
void swap(int &x, int &y)
。输入格式
共一行,包含两个整数 x 和 y。
输出格式
共一行,包含交换后的 x 和 y。
输入样例
1
3 5
输出样例
1
5 3
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using namespace std;
void swap(int &x, int &y)
{
int temp = x;
x = y;
y = temp;
}
int main()
{
int x, y;
cin >> x >> y;
swap(x, y);
cout << x << ' ' << y;
return 0;
}打印数字
输入一个长度为 n 的数组 a 和一个整数 size,请你编写一个函数,
void print(int a[], int size)
, 打印数组 a 中的前 size 个数。输入格式
第一行包含两个整数 n 和 size。
第二行包含 n 个整数 a[i],表示整个数组。
输出格式
共一行,包含 size 个整数,表示数组的前 size 个数。
输入样例
1
25 3
1 2 3 4 5输出样例
1
1 2 3
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using namespace std;
void print(int a[], int size)
{
for (int i = 0; i < size; i ++)
cout << a[i] << ' ';
cout << endl;
}
int main()
{
int n, size;
int a[1001];
cin >> n >> size;
for (int i = 0; i < n; i ++)
cin >> a[i];
print(a, size);
return 0;
}打印矩阵
给定一个
row×col
的二维数组 a,请你编写一个函数,void print2D(int a[][N], int row, int col)
,打印数组构成的row
行,col
列的矩阵。注意,每打印完一整行需要输出一个回车。
输入格式
第一行包含两个整数
row
,col
。接下来
row
行,每行包含col
个整数,表示完整二维数组a
输出格式
共
row
行,每行col
个整数,表示打印出的矩阵。输入样例
1
2
3
43 4
1 3 4 5
2 6 9 4
1 4 7 5输出样例
1
2
31 3 4 5
2 6 9 4
1 4 7 5解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using namespace std;
void print2D(int a[][100], int row, int col)
{
for (int i = 0; i < row; i ++)
{
for (int j = 0; j < col; j ++)
cout << a[i][j] << ' ';
cout << endl;
}
}
int main()
{
int row, col;
int a[100][100];
cin >> row >> col;
for (int i = 0; i < row; i ++)
for (int j = 0; j < col; j ++)
cin >> a[i][j];
print2D(a, row, col);
return 0;
}递归求阶乘
请使用递归的方式求 n 的阶乘。
输入格式
共一行,包含一个整数 n。
输出格式
共一行,包含一个整数,表示 n 的阶乘的值。
输入样例
1
3
输出样例
1
6
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using namespace std;
int fact(int n)
{
if (n == 1)
return 1;
else
return n * fact(n - 1);
}
int main()
{
int n;
cin >> n;
cout << fact(n) << endl;
return 0;
}递归求斐波那契数列
请使用递归的方式求斐波那契数列的第 n 项,下标从1开始。
斐波那契数列:1,1,2,3,5…,这个数列从第 3 项开始,每一项都等于前两项之和
输入格式
共一行,包含整数 n。
输出格式
共一行,包含一个整数,表示斐波那契数列的第 n 项。
输入样例
1
4
输出样例
1
3
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using namespace std;
int ph(int n)
{
if (n == 1)
return 1;
else if ( n == 2)
return 1;
else
return ph(n - 1) + ph(n - 2);
}
int main()
{
int n;
cin >> n;
cout << ph(n) << endl;
return 0;
}
习题
绝对值
输入一个整数 x,请你编写一个函数,
int abs(int x)
,输出 x 的绝对值。输入格式
共一行,包含一个整数 x。
输出格式
共一行,包含 x 的绝对值。
输入样例
1
-3
输出样例
1
3
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using namespace std;
int abs(int x)
{
if (x >= 0)
return x;
else
return (-x);
}
int main()
{
int x;
cin >> x;
cout << abs(x) << endl;
return 0;
}两个数的和
输入两个浮点数 x 和 y,请你编写一个函数,
double add(double x, double y)
,计算并输出 x 与 y 的和。输入格式
共一行,包含两个浮点数 x 和 y。
输出格式
共一行,包含一个浮点数,表示两个数的和,结果保留 2 位小数。
输入样例
1
1.11 2.22
输出样例
1
3.33
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using namespace std;
double add(double x, double y)
{
return (x + y);
}
int main()
{
double x, y;
cin >> x >> y;
double z = add(x, y);
printf("%.2lf", z);
return 0;
}区间求和
输入两个整数 l 和 r,请你编写一个函数,
int sum(int l, int r)
,计算并输出区间 [l,r] 内所有整数的和。输入格式
共一行,包含两个整数 l 和 r。
输出格式
共一行,包含一个整数,表示所求的和。
输入样例
1
3 5
输出样例
1
12
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using namespace std;
int sum(int l, int r)
{
int s = 0;
for (int i = l; i <= r; i ++)
s += i;
return s;
}
int main()
{
int l, r;
cin >> l >> r;
cout << sum(l, r);
return 0;
}最小公倍数
输入两个整数 a 和 b,请你编写一个函数,
int lcm(int a, int b)
,计算并输出 a 和 b 的最小公倍数。输入格式
共一行,包含两个整数 a 和 b。
输出格式
共一行,包含一个整数,表示 a 和 b 的最小公倍数。
输入样例
1
6 8
输出样例
1
24
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using namespace std;
int lcm(int a, int b)
{
for (int i = a; i < a * b; i ++)
{
if (i % a == 0 && i % b == 0)
return i;
}
}
int main()
{
int a, b;
cin >> a >> b;
if (a < b)
swap(a, b);
cout << lcm(a, b) << endl;
return 0;
}复制数组
给定两个数组 a 和 b 以及一个整数 size,请你编写一个函数,
void copy(int a[], int b[], int size)
,将 a 数组中的前 size 个数字,复制到 b 数组中。复制完成后,输出 b 数组。
输入格式
第一行包含整数 n,m,size,分别表示 a 数组的长度,b 数组的长度以及整数 size。
第二行包含 n 个整数,表示数组 a。
第三行包含 m 个整数,表示数组 b。
输出格式
共一行,包含 m 个整数,表示复制完成后的数组 b。
输入样例
1
2
33 5 2
1 2 3
4 5 6 7 8输出样例
1
1 2 6 7 8
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using namespace std;
void copy(int a[], int b[], int size)
{
for (int i = 0; i < size; i ++)
b[i] = a[i];
}
int main()
{
int a[100], b[100];
int n, m, size;
cin >> n >> m >> size;
for (int i = 0; i < n; i ++)
cin >> a[i];
for (int i = 0; i < m; i ++)
cin >> b[i];
copy(a, b, size);
for (int i = 0; i < m; i ++)
cout << b[i] << ' ';
return 0;
}打印字符串
给定一个字符串,请你编写一个函数,
void print(char str[])
,将这个字符串打印出来。输入格式
共一行,包含一个字符串。
输出格式
共一行,表示打印出的字符串。
输入样例
1
Darling in the Franxx.
输出样例
1
Darling in the Franxx.
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using namespace std;
void print(char str[])
{
cout << str;
}
int main()
{
char str[101];
fgets(str, 101, stdin);
print(str);
return 0;
}数组翻转
给定一个长度为 n 的数组 a 和一个整数 size,请你编写一个函数,
void reverse(int a[], int size)
,实现将数组 a 中的前 size 个数翻转。输出翻转后的数组 a。
输入格式
第一行包含两个整数 n 和 size。
第二行包含 n 个整数,表示数组 a。
输出格式
共一行,包含 n 个整数,表示翻转后的数组 a。
输入样例
1
25 3
1 2 3 4 5输出样例
1
3 2 1 4 5
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using namespace std;
void reverse(int a[], int size)
{
int b[1001];
for (int i = 0; i < size; i ++)
b[i] = a[i];
for (int j = 0; j < size; j ++)
a[j] = b[size - j - 1];
}
int main()
{
int n, size;
cin >> n >> size;
int a[1001];
for (int i = 0; i < n; i ++)
cin >> a[i];
reverse(a, size);
for (int i = 0; i < n; i ++)
cout << a[i] << ' ';
return 0;
}数组去重
给定一个长度为 n 的数组 a,请你编写一个函数:
int get_unique_count(int a[], int n)
,返回数组前n个数中的不同数的个数输入格式
第一行包含一个整数 n。
第二行包含 n 个整数,表示数组 a。
输出格式
共一行,包含一个整数表示数组中不同数的个数。
输入样例
1
25
1 1 2 4 5输出样例
1
4
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using namespace std;
int get_unique_count(int a[], int n)
{
int s[1001] = {0};
for (int i = 0; i < n; i ++)
s[a[i]] ++;
int cnt = 0;
for (int j = 1; j <= 1001; j ++)
if (s[j] != 0)
cnt ++;
return cnt;
}
int main()
{
int n;
int a[1001];
cin >> n;
for (int i = 0; i < n; i ++)
cin >> a[i];
cout << get_unique_count(a, n) << endl;;
return 0;
}数组排序
给定一个长度为 n 的数组 a 以及两个整数 l 和 r,请你编写一个函数,
void sort(int a[], int l, int r)
,将 a[l]∼a[r] 从小到大排序。输出排好序的数组 a。
输入格式
第一行包含三个整数 n,l,r。
第二行包含 n 个整数,表示数组 a。
输出格式共一行,包含 n 个整数,表示排序完成后的数组 a。
输入样例
1
25 2 4
4 5 1 3 2输出样例
1
4 5 1 2 3
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using namespace std;
void sort(int a[], int l, int r)
{
for (int i = l; i <= r; i ++)
{
for (int j = i + 1; j <= r; j ++)
{
if (a[i] > a[j])
{
int tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}
}
}
}
int main()
{
int n, l, r;
cin >> n >> l >> r;
int a[1001];
for (int i = 0; i < n; i ++)
cin >> a[i];
sort(a, l, r);
for (int i = 0; i < n; i ++)
cout << a[i] << ' ';
return 0;
}跳台阶
一个楼梯共有 n 级台阶,每次可以走一级或者两级,问从第 0 级台阶走到第 n 级台阶一共有多少种方案。
输入格式
共一行,包含一个整数 n。
输出格式
共一行,包含一个整数,表示方案数。
输入样例
1
5
输出样例
1
8
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24//想要到第n级台阶一共有两种方法,即从 n-1 级台阶走一级或从 n-2 级台阶走两级,转换成函数递归问题求 f(1)=1 和f(2)=2 的斐波那契数列
using namespace std;
int stairs(int n)
{
if (n == 1)
return 1;
else if (n == 2)
return 2;
else
return stairs(n - 1) + stairs(n - 2);
}
int main()
{
int n;
cin >> n;
cout << stairs(n) << endl;
return 0;
}走方格
给定一个 n×m 的方格阵,沿着方格的边线走,从左上角 (0,0) 开始,每次只能往右或者往下走一个单位距离,问走到右下角 (n,m) 一共有多少种不同的走法。
输入格式
共一行,包含两个整数 n 和 m。
输出格式
共一行,包含一个整数,表示走法数量。
输入样例
1
2 3
输出样例
1
10
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using namespace std;
int squa(int n, int m)
{
if (n == 0 || m == 0)
return 1;
else
return squa(n, m - 1) + squa(n - 1, m);
}
int main()
{
int n, m;
cin >> n >> m;
cout << squa(n, m) << endl;
return 0;
}排列
给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。
现在,请你按照字典序将所有的排列方法输出。
输入格式
共一行,包含一个整数 n。
输出格式
按字典序输出所有排列方案,每个方案占一行。
输入样例
1
3
输出样例
1
2
3
4
5
61 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using namespace std;
const int N = 10;
int n;
void dfs(int u,int nums[], bool st[])
{
if (u > n) //如果当前要填数的位置大于总位数则输出
{
for (int i = 1; i <= n; i ++)
cout << nums[i] << ' ';
cout << endl;
}
else
{
for (int i = 1; i <= n; i ++)
{
if (!st[i]) //寻找还没有被用过的数
{
st[i] = true;
nums[u] = i;
dfs(u + 1, nums, st);
st[i] = false; //恢复现场
}
}
}
}
int main()
{
cin >> n;
int nums[N];
bool st[N] = {0};
dfs(1, nums, st);
return 0;
}