Java语法笔记(六):函数
函数基础
一个典型的函数定义包括以下部分:修饰符、返回类型、函数名字、由0个或多个形参组成的列表以及函数体。
编写函数
1 | public class Main |
函数名字是fact
,它作用于一个整型参数,返回一个整型值。return
语句负责结束fact
并返回res
的值。
修饰符包括private
、static
等,它们属于类相关的概念,会在下一章解释。
调用函数
1 | import java.util.Scanner; |
输入
1 | 5 |
输出
1 | 120 |
函数的调用完成两项工作:一是用实参初始化函数对应的形参,二是将控制权转移给被调用函数。此时,主调函数的执行被暂时中断,被调函数开始执行。
形参和实参
实参是形参的初始值。第一个实参初始化第一个形参,第二个实参初始化第二个形参,依次类推。形参和实参的类型和个数必须匹配。
1 | fact("hello"); // 错误:实参类型不正确 |
函数的形参列表
函数的形参列表可以为空,但是不能省略。
1 | void f1() {/* …. */} // 空形参列表 |
形参列表中的形参通常用逗号隔开,其中每个形参都是含有一个声明符的声明。即使两个形参的类型一样,也必须把两个类型都写出来:
1 | int f3(int v1, v2) {/* … */} // 错误 |
函数的返回类型
大多数类型都能用作函数的返回类型。一种特殊的返回类型是void
,它表示函数不返回任何值。
函数的返回类型也可以是数组、字符串或者其他对象:
1 | import java.util.Arrays; |
输出
1 | [1, 2, 3] |
变量的作用域
函数内定义的变量为局部变量,只能在函数内部使用。
定义在类中的变量为成员变量,可以在类的所有成员函数中调用。
当局部变量与全局变量重名时,会优先使用局部变量。
1 | public class Main { |
输出
1 | 3 |
参数传递
值传递
八大基本数据类型和String
类型等采用值传递。
将实参的初始值拷贝给形参。此时,对形参的改动不会影响实参的初始值。
1 | public class Main { |
输出
1 | 10 |
引用传递
除String
以外的数据类型的对象,例如数组、StringBuilder
等采用引用传递。
将实参的引用(地址)传给形参,通过引用找到变量的真正地址,然后对地址中的值修改。所以此时对形参的修改会影响实参的初始值。
1 | import java.util.Arrays; |
输出
1 | [5, 4, 3, 2, 1] |
返回类型和return
语句
return
语句终止当前正在执行的函数并将控制权返回到调用该函数的地方。return
语句有两种形式:
1 | return; |
无返回值函数
没有返回值的return
语句只能用在返回类型是void
的函数中。返回void
的函数不要求非得有return
语句,因为在这类函数的最后一句后面会隐式地执行return
。
通常情况下,void
函数如果想在它的中间位置提前退出,可以使用return
语句。
1 | public class Main { |
输出
1 | 4 3 |
有返回值的函数
只要函数的返回类型不是void
,则该函数内的每个分支都必须有return
语句,且每条return
语句都必须返回一个值。return
语句返回值的类型必须与函数的返回类型相同,或者能隐式地转换函数的返回类型。
1 | import java.util.Scanner; |
输入
1 | 3 4 |
输出
1 | 4 |
函数重载
函数重载是指在同一个类中存在多个函数,函数名称相同但参数列表不同。
1 | import java.util.Scanner; |
输出
1 | int max |
函数递归
在一个函数内部,也可以调用函数本身。
1 | //求斐波那契数列的第n项 |
输入
1 | 6 |
输出
1 | 8 |
例题
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
16import java.util.Scanner;
public class Main {
private static int fact(int n) {
int ans = 1;
for (int i = 1; i <= n ;i ++)
ans *= i;
return ans;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.print(fact(n));
}
}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
17import java.util.Scanner;
public class Main {
private static int max(int x, int y) {
if (x > y)
return x;
else
return y;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int y = sc.nextInt();
System.out.println(max(x, y));
}
}最大公约数
输入两个整数 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
24import java.util.Scanner;
public class Main {
private static int gcd(int a, int b) {
if (a > b) {
int tmp = a;
a = b;
b = tmp;
}
for (int i = a; i >= 1; i --)
if ((a % i == 0) && (b % i == 0))
return i;
return 1;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int y = sc.nextInt();
System.out.println(gcd(x, y));
}
}交换数值
输入两个整数 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
18import java.util.Scanner;
public class Main {
private static void swap(int[] a) {
int tmp = a[0];
a[0] = a[1];
a[1] = tmp;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] a = new int[2];
a[0] = sc.nextInt();
a[1] = sc.nextInt();
swap(a);
System.out.printf("%d %d", a[0], a[1]);
}
}打印数字
输入一个长度为 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
18import java.util.Scanner;
public class Main {
private static void print(int a[], int size) {
for (int i = 0; i < size; i ++)
System.out.printf("%d ", a[i]);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int size = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i ++)
a[i] = sc.nextInt();
print(a, size);
}
}打印矩阵
给定一个
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
23import java.util.Scanner;
public class Main {
private static void print2D(int a[][], int row, int col) {
for (int i = 0; i < row; i ++) {
for (int j = 0; j < col; j ++)
System.out.printf("%d ", a[i][j]);
System.out.println();
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int r = sc.nextInt();
int c = sc.nextInt();
int[][] a = new int[r][c];
for (int i = 0; i < r; i ++)
for (int j = 0; j < c; j ++)
a[i][j] = sc.nextInt();
print2D(a, r, c);
}
}递归求阶乘
请使用递归的方式求 n 的阶乘。
输入格式
共一行,包含一个整数 n。
输出格式
共一行,包含一个整数,表示 n 的阶乘的值。
输入样例
1
3
输出样例
1
6
解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import java.util.Scanner;
public class Main {
private static int fact(int n) {
if (n == 1)
return 1;
else
return n * fact(n - 1);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(fact(n));
}
}递归求斐波那契数列
请使用递归的方式求斐波那契数列的第 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
14import java.util.Scanner;
public class Main {
private static int fib(int n) {
if (n <= 2) return 1;
else return fib(n - 1) + fib(n - 2);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(fib(n));
}
}
习题
绝对值
输入一个整数 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
14import java.util.Scanner;
public class Main {
private static int abs(int x) {
if (x >= 0) return x;
else return -x;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
System.out.println(abs(x));
}
}两个数的和
输入两个浮点数 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
14import java.util.Scanner;
public class Main {
private static double add(double x, double y) {
return x + y;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double x = sc.nextDouble();
double y = sc.nextDouble();
System.out.printf("%.2f", add(x, y));
}
}区间求和
输入两个整数 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
17import java.util.Scanner;
public class Main {
private static int sum(int l, int r) {
int s = 0;
for (int i = l; i <= r; i ++)
s += i;
return s;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int y = sc.nextInt();
System.out.println(sum(x, y));
}
}最小公倍数
输入两个整数 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
24import java.util.Scanner;
public class Main {
private static int lcm(int a, int b) {
if (a < b) {
int tmp = a;
a = b;
b = tmp;
}
for (int i = a; i < a * b; i ++)
if ((i % a == 0) && (i % b == 0))
return i;
return a * b;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
System.out.println(lcm(a, b));
}
}复制数组
给定两个数组 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
24import java.util.Scanner;
public class Main {
private static void copy(int a[], int b[], int size) {
for (int i = 0; i < size; i ++)
b[i] = a[i];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int size = sc.nextInt();
int[] a = new int[n];
int[] b = new int[m];
for (int i = 0; i < n; i ++)
a[i] = sc.nextInt();
for (int i = 0; i < m; i ++)
b[i] = sc.nextInt();
copy(a, b, size);
for (int i = 0; i < m; i ++)
System.out.printf("%d ", b[i]);
}
}打印字符串
给定一个字符串,请你编写一个函数,
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
15import java.util.Scanner;
import java.util.Arrays;
public class Main {
private static void print(char str[]) {
System.out.println(str);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
char[] strs = str.toCharArray();
print(strs);
}
}数组翻转
给定一个长度为 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
24import java.util.Scanner;
import java.util.Arrays;
public class Main {
private static void reverse(int a[], int size) {
for (int i = 0, j = size - 1; i < j; i ++, j --) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int size = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i ++)
a[i] = sc.nextInt();
reverse(a, size);
for (int i = 0; i < n; i ++)
System.out.printf("%d ", a[i]);
}
}数组去重
给定一个长度为 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
24import java.util.Scanner;
public class Main {
private static int get_unique_count(int a[], int n) {
int cnt = 0;
int[] s = new int[1001];
for (int i = 0; i < n; i ++)
s[a[i]] ++;
for (int i = 0; i < 1001; i ++)
if (s[i] != 0)
cnt ++;
return cnt;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i ++)
a[i] = sc.nextInt();
System.out.println(get_unique_count(a, n));
}
}数组排序
给定一个长度为 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
解