자기자신 안에 자기 자신이 있는것을 재귀함수라 한다.
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <stdio.h>
//recursion
void rec(int n) {
printf("n=%d\n",n);
rec(n+1);
}
int main() {
rec(1);
}
|
cs |
rec함수가 미쳐끝나기도 전에 다시 rec가 호출되는 형태를 띈다.
예를 들어 1이 들어가면 함수가 끝나기도 전에 rec(2)가 호출되게 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <stdio.h>
//recursion
void rec(int n) {
if (n > 5) {
return;
}
printf("n=%d\n",n);
rec(n+1);
}
int main() {
rec(1);
}
|
cs |
if문을 사용해서 무한반복이 되는걸 막아볼거다.
매개변수 n에 6이 들어가면 return을 만나서 함수가 종료되게 된다.
그러면 아직 n이 5인 상태가 함수가 종료되지 않았기 때문에 중괄호를 닫으며 n이 5인경우 종료
n이 4인경우로 돌아가서 n이5인경우가 종료되었기때문에 중괄호 닫으며 n이 4인경우가 종료된다.
이렇게 1까지 돌아가면서 함수가 종료된다.
팩토리얼을 재귀로 구현
n!=n*(n-1)! 이라고 생각하고 코드를 구현해보면된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <stdio.h>
//recursion
//n!=n*(n-!)!
int factorial(int n) {
//n을 매개변수로 받으면 n!리턴
if (n == 1) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
printf("%d ",factorial(3));
}
|
cs |
어떻게 실행되는지 살펴보자.
우선 factorial 함수에 3이 들어가면 3*factorial(2)가 반환되고 바로 factorial(2)가 실행된다. factorial(2)는 2*factorial이 반환되고 함수가 종료되기 전에 factorial(1)이 실행되는데 n이 1일때는 조건문에 걸리기 때문에 1이 반환되며 종료된다.
아직 종료되지 않은 n이 2일때로 돌아가면 2*1을 하며 n이 2일때 함수가 종료되고, n이 3일때로 돌아가면 3*2를 하며 비로소 모든 함수가 종료된다.
재귀 연습문제
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <stdio.h>
void rec(int n) {
if (n == 0) return;
printf("%d\n", n);
rec(n - 1);
printf("%d\n", n);
}
int main() {
rec(5);
}
|
cs |
답은
5
4
3
2
1
1
2
3
4
5
배열을 매개변수로 넘기기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include <stdio.h>
void printArr(int arr[4]) {
for (int i = 0; i < 4; i++) {
printf("%d ", arr[i]);
}
}
int main() {
int arr[4] = { 1,2,3,4 };
printArr(arr);
}
|
cs |
이렇게 배열을 전달하는게 call-by value인지 call-by reference인지 궁금해진다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <stdio.h>
void printArr(int arr[4]) {
for (int i = 0; i < 4; i++) {
arr[i] *= 2;
}
}
int main() {
int arr[4] = { 1,2,3,4 };
printArr(arr);
for (int i = 0; i < 4; i++) {
printf("%d ",arr[i]);
}
|
cs |
8번째 줄처럼 arr[i] *= 2; 를 해줬을 때 모든 원소의 값이 2배만큼 되어 출력되면 call -by reference일거고, 아니면 call-by value일것이다.
2468로 변했기 때문에 call-by refernece인것을 알수 있다.
포인터와 배열에는 밀접한 관계가 있는데, 앞서 포인터를 배열처럼 사용할 수 있다는 것을 배웠다.
그래서 4번째 줄의 매개변수인 int arr[4]는 사실상 int *arr로 봐줘도 된다.
그리고 13번째 줄에 prinArr(arr) 또한 printArr(&arr[0])과 같다.
arr이 위 사진과 같은 임의의 주소값을 가지고 있다고 가정해보자.
&arr[0]이 printArr로 넘어가고
arr[i] *= 2; <-- 이게 헷갈리면 *(arr+i)*= 2;로 바꿔줘도 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <stdio.h>
void printArr(int arr[2][3]) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
int arr[2][3] = { {1,2,3},{4,5,6} };
printArr(arr);
}
|
cs |
2차원 배열또한 잘 출력되는 것을 확인할 수 있는데, 얘도 포인터로 바꿔보면
2차원 배열을 배열포인터 쓰듯이 쓰면된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <stdio.h>
void printArr(int (*arr)[3]) {//배열포인터에는 arr[0][0]의 주소값이 들어감
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", arr[i][j]); //2차원배열을 쓰나 배열포인터를 쓰다 같다.
}
printf("\n");
}
}
int main() {
int arr[2][3] = { {1,2,3},{4,5,6} };
printArr(arr); //&arr[0] --> 0번째 행 전체를 가리키는 포인터가 넘어감
}
|
cs |
15번째 줄에 printArr(arr); 하면서 printArr함수에 0번째 행 전체를 가리키는 포인터가 넘어갔다.
4번째 줄에 void printArr(int (*arr)[3]) 를 보면 배열 포인터가 들어 가있는데 여기로 0번째 행 전체를 가리키는 포인터가
들어가게 된다. 그렇게 되면 8번째 줄에 arr[i][j]에서는 2차원배열을 쓰나 배열포인터를 쓰나 둘다 같게 된다.
정리하자면!!
일차원 배열, 이차원 배열 모두다 printArr함수는 call-by reference형태로 넘겨진다고 보면된다.
함수 연습문제
문자열의 공백이 없게 출력될 수 있는 프로그램을 만들어라.
문제를 풀어가는 과정은
1. 두개의 문자열을 각각 담아줄 char형 배열 2개를 생성한다.
2.print_noSpace에 매개변수로 배열을 받아준다.
3. char형 배열은 끝에 공백문자 \0가 있기에 null문자 전까지 문자열을 돌려준다음 그 중에 공백을 제거한다.
정답코드는
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <stdio.h>
#include <string.h>
void print_noSpace(char str[]) {
for (int i = 0; str[i] != '\0'; i++) {
//null문자 되면 프로그램종료
if (str[i] != ' ') {
printf("%c", str[i]);
}
}
}
int main() {
char s[] = "Hello,World\n";
char s1[] = "My name is Meaning\n";
print_noSpace(s);
print_noSpace(s1);
}
|
cs |
내가 놓쳤던 부분은 for문에서 i<n 꼴이 아니라 str[i] != '\0'꼴로 써줘도 된다는 점이고,
%s가 아니라 %c로 써줘도 된다는 것을 놓쳤다.
cf) %s와 %c의 차이점
%s는 주소값을 받고 그 주소값안에 저장되어 있는 문자를 시작으로 \0이 나올때까지 문자열을 출력
%c는 실제 문자를 받아서 그 문자열을 출력
부끄럽지만 내가 쓴 코드는
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <stdio.h>
#include <string.h>
void print_noSpace(char str[]) {
char arr[100];
for (int i = 0; i < strlen(str); i++) {
if (str[i] != ' '&&str[i]!='\0') {
arr[i] = str[i];
}
}
printf("%s", &arr);
}
int main() {
char s[] = "Hello,World\n";
char s1[] = "My name is Meaning\n";
print_noSpace(s);
print_noSpace(s1);
}
|
cs |
이거였는데 출력하고나니 문자들이 많이 깨져있었다.
'C > 기초(두들낙서)' 카테고리의 다른 글
[C기초] 구조체 포인터, 구조체에 함수 집어넣기 (0) | 2022.01.11 |
---|---|
[C기초] 구조체 (0) | 2022.01.10 |
[C기초] 함수 반환/호출/프로토타입 (0) | 2022.01.09 |
[C기초] 포인터와 배열 연습문제 (0) | 2022.01.08 |
[C기초] 포인터 배열 (0) | 2022.01.04 |
댓글