강의 내용 및 자료 출처: 권오흠 교수님
Theme. 함수
1. return 값이 있는 함수
if(k<2) { return false } 부분은 1이 소수로 포함되지 않도록 하는 부분!
2. return 값이 없는 함수
사용자로부터 n개의 정수를 입력받은 후 오름차순으로 정렬(sort)하여 출력해라.
Bubble sort를 이용한 함수를 생성하여 코드를 작성해본다.
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
|
package CH1;
import java.util.Scanner;
public class Code18 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] data = new int[n];
for (int i = 0; i < n; i++) {
data[i] = sc.nextInt();
}
sc.close();
bubblesort(n, data);
System.out.print("Sorted data: ");
for (int i = 0; i < n; i++) {
System.out.print(data[i] + " ");
}
}
static void bubblesort(int n, int[] data) {
for (int i = n-1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if(data[j] > data[j+1]) {
int tmp = data[j];
data[j] = data[j+1];
data[j+1] = tmp;
}
}
}
return;
}
}
|
cs |
이때, swap하는 과정을 함수로 나타내어 호출하고자 아래와 같은 코드를 작성하면,
실행시켜보면, 정렬이 되지 않는다. 무엇이 문제일까?
"값에 의한 호출"에 대해 이해하면 그 이유를 알 수 있다.
매개변수의 전달과정에서
호출문의 data[j], data[j+1]은 각각 data 배열에 존재하는 값(배열의 한 칸에 해당)으로 actual parameter이다.
호출된 메서드의 a, b는 formal parameter이다.
"값에 의한 호출"이란 결론적으로 말하면 actual parameter와 formal parameter는 별개의 변수라는 것(메모리 영역에서 서로 다른 영역을 차지한다)이다.
다만, 메서드를 호출하는 순간(호출문이 실행되는 순간) actual parameter 값이 formal parameter에 복사가 된다.
즉, 값만 복사가 되는 것이지 서로 별개의 변수이므로 a,b를 스왑한다고 해서 data[j], data[j+1]이 스왑되는 것은 아니다.
복사본들끼리 스왑한다고 원본들이 스왑되는 것은 아니다라고 이해해도 좋다.
그런데!!
swap메서드를 추가하지 않고, bubblesort 메서드만을 이용하여 코드를 작성했을 때에도,
호출문: bubblesort(n, data);
호출된 메서드: static void bubblesort(int n, int[] data); ...에서
"값에 의한 호출"에 의해 정렬이 올바르게 되지 않았어야 하는 것이 아닌가? 라는 의문이 들 수 있다.
하지만, 정렬은 올바르게 된다.
무슨 차이점이 있는가?
답은 "배열"에 있다. 정확히 말하자면, 배열만이 예외는 아니다.
즉, 기본형(primitive type)의 매개변수(8가지)는 호출된 메서드에서 값을 변경하더라도 호출한 쪽에 영향을 주지 못한다. 이것은 "값에 의한 호출"이기 때문이다.
하지만, 배열은 참조형 변수다. 따라서, "값에 의한 호출"에 영향을 받지 않는다.
배열의 값은 호출된 메서드에서 변경하면 호출한 쪽에서도 변경된다.
txt파일에 몇 명의 사람들이 존재하는지 모르므로 배열의 길이를 1000으로 둔 것.
하지만, 위와 같이 코드를 작성하면 FileNotFoundException이 발생한다. try catch문을 작성하도록 한다.
위 코드에서의 return은 main 메서드를 종료하게 되는데, 이는 곳 프로그램 종료를 의미하므로 System.exit(0)으로 대체할 수 있다.
여러 개의 클래스에 사용되는 변수가 존재하므로, 그 변수들을 멤버변수로 선언한다.
위 코드의 name[j] > name[j+1] 부분에서 에러가 발생한다.
각각 String의 값이기 때문인데,
문자열 간의 사전식 순서를 검사하기 위한 compareTo메서드는 1,0,-1 3가지 값을 반환하게 된다.
즉, name[j].compareTo(name[j+1]) < 0 이면, name[j]가 name[j+1]보다 사전식 순서가 앞에 위치하는 것이고(순서가 더 빠르다)
name[j].compareTo(name[j+1]) = 0 이면, name[j]와 name[j+1]의 사전식 순서가 동일하다는 것이며
name[j].compareTo(name[j+1]) > 0 이면, name[j]가 name[j+1]보다 사전식 순서가 뒤에 위치하는 것(순서가 더 느리다)이다.
여기서는 쓰이지 않았지만, 두 문자열 str1, str2에 대해서 두 문자열이 동일한지, 동일하면 true(1), 동일하지 않다면 false(0)를 반환하는 메서드는 equals다. 즉, str1.equals(str2)와 같이 사용하면 된다.
2가지 방법으로 풀 수 있는데,
먼저, 첫 번째 방법의 코드는 다음과 같다.
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
package CH1;
import java.util.Scanner;
public class Code21 {
static int n;
static int[][] grid;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
grid = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
grid[i][j] = sc.nextInt();
}
}
for (int x = 0; x < n; x++) {
for (int y = 0; y < n; y++) {
for (int dir = 0; dir < 8; dir++) {
for (int len = 1; len <= n; len++) {
int val = computeValue(x,y,dir,len);
if(val != -1 && isPrime(val)) {
System.out.println(val);
}
}
}
}
}
}
public static int computeValue(int x, int y, int dir, int len) {
int val = 0;
for (int i = 0; i < len; i++) {
int digit = getDigit(x,y,dir,i);
if(digit == -1) {
return -1;
}
val = val * 10 + digit;
}
return val;
}
public static int getDigit(int x, int y, int dir, int k) {
int newX = x;
int newY = y;
switch(dir) {
case 0: newY -= k; break;
case 1: newX += k; newY -= k; break;
case 2: newX += k; break;
case 3: newX += k; newY += k; break;
case 4: newY += k; break;
case 5: newX -= k; newY += k; break;
case 6: newX -= k; break;
case 7: newX -= k; newY -= k; break;
}
if(newX < 0 || newX >= n || newY < 0 || newY >= n) {
return -1;
}
return grid[newX][newY];
}
public static boolean isPrime(int val) {
boolean b = true;
if(val < 2) {
b = false;
}
for (int i = 2; i*i <= val ; i++) {
if(val % i == 0) {
b = false;
break;
}
}
return b;
}
}
|
cs |
val = val * 10 + digit 부분에 해당
i칸 떨어진 자리에 있는 digit를 반환하는 것이기 때문에, i는 i == 0(즉, 한자리 수)부터 i == (len-1)(즉, len자리 수)까지 증가할 수 있다.
이때, x와 y의 양의 방향을 각각 오른쪽 방향, 아래쪽 방향으로 잡았다.
두번째 방법의 코드에서는 아래와 같이 좌표의 증감분에 대한 배열들을 미리 만들어 놓아서 첫번째 코드의 switch문을 대신할 수 있다.
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
package CH1;
import java.util.Scanner;
public class Code21 {
static int n;
static int[][] grid;
static int[] offsetX = {0,1,1,1,0,-1,-1,-1};
static int[] offsetY = {-1,-1,0,1,1,1,0,-1};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
grid = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
grid[i][j] = sc.nextInt();
}
}
for (int x = 0; x < n; x++) {
for (int y = 0; y < n; y++) {
for (int dir = 0; dir < 8; dir++) {
for (int len = 1; len <= n; len++) {
int val = computeValue(x,y,dir,len);
if(val != -1 && isPrime(val)) {
System.out.println(val);
}
}
}
}
}
}
public static int computeValue(int x, int y, int dir, int len) {
int val = 0;
for (int i = 0; i < len; i++) {
int digit = getDigit(x,y,dir,i);
if(digit == -1) {
return -1;
}
val = val * 10 + digit;
}
return val;
}
public static int getDigit(int x, int y, int dir, int k) {
int newX = x + k*offsetX[dir];
int newY = y + k*offsetY[dir];
if(newX < 0 || newX >= n || newY < 0 || newY >= n) {
return -1;
}
else {
return grid[newX][newY];
}
}
public static boolean isPrime(int val) {
boolean b = true;
if(val < 2) {
b = false;
}
for (int i = 2; i*i <= val ; i++) {
if(val % i == 0) {
b = false;
break;
}
}
return b;
}
}
|
cs |
메서드 끝.
'Java > Java로 배우는 자료구조' 카테고리의 다른 글
자료구조 2-2. 메서드와 생성자 (0) | 2023.02.13 |
---|---|
자료구조 2-1. 클래스, 객체, 참조변수(2) (0) | 2023.02.13 |
자료구조 2-1. 클래스, 객체, 참조변수(1) (0) | 2023.02.08 |
자료구조 1-3. 문자열 (0) | 2023.02.06 |
자료구조 1-1 중 변수 (0) | 2023.01.30 |