programming/C++프로그래밍 개념

[C로 배우는 쉬운 자료구조] Chapter2(자료구조 구현을 위한 C프로그래밍 기법) 정리 및 연습문제

주니어개발자 2021. 5. 26. 17:02

 

Chapter2 에는 여러 가지 기법이 있지만

 

어렵다고 생각되는, 이중 포인터, 재귀호출 이 두 가지를 정리해보겠다.

 

 

 


 

포인터

 

내용 정리

포인터에 관련된 내용은 C프로그래밍에서 배웠으니, 이중 포인터만 정리하고 넘어간다.

 

 

 

※ 이중 포인터
포인터의 포인터 즉, 포인터를 가리키고 있는 포인터.

 

char **ptr의 모습

 

 


 

연습 문제

바로 이중포인터 연습문제 풀이를 통해서, 쉽게 이해 하자.

 

 

예제 2-11 포인터 배열과 포인터의 포인터 사용하기.

 

 

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
#include <stdio.h>
 
int main()
{
    char *ptrarr[2];
    char **dptr;
    int i;
 
    ptrarr[0= "Seoul";
    ptrarr[1= "Mapo";
 
    //이중 포인터 변수에 포인터변수의 주소를 할당(배열명은 포인터와 유사)
    dptr = ptrarr;  
    
    //포인터 배열 이용한 출력
    printf("\n ptrarr[0]의 주소 (&ptrarr[0]) = %u"&ptrarr[0]);
    printf("\n ptrarr[0]의 값 (ptrarr[0]) = %u", ptrarr[0]);
    printf("\n ptrarr[0]의 참조값 (*ptrarr[0]) = %c"*ptrarr[0]);
    printf("\n ptrarr[0]의 참조 문자열 (*ptrarr) = %s \n"*ptrarr);
 
    printf("\n ptrarr[1]의 주소 (&ptrarr[1]) = %u"&ptrarr[1]);
    printf("\n ptrarr[1]의 값 (ptrarr[1]) = %u", ptrarr[1]);
    printf("\n ptrarr[1]의 참조값 (*ptrarr[1]) = %c"*ptrarr[1]);
    printf("\n ptrarr[1]의 참조 문자열 (*(ptrarr+1)) = %s \n"*(ptrarr+1));
 
    //이중 포인터 이용한 출력
    printf("\n dptr의 주소 (&dptr) = %u"&dptr);
    printf("\n dptr의 값 (dptr) = %u", dptr);
    printf("\n dptr의 1차 참조값 (*dptr) = %u"*dptr);
    printf("\n dptr의 2차 참조값 (**dptr) = %c"**dptr);
    printf("\n dptr의 2차 참조 문자열 (*dptr) = %s \n"*dptr);
 
    printf("\n ptrarr의 주소 (&ptrarr) = %u"&ptrarr);
    printf("\n ptrarr의 값 (ptrarr) = %u", ptrarr);
    printf("\n ptrarr의 1차 참조값 (*ptrarr) = %u"*ptrarr);
    printf("\n ptrarr의 2차 참조값 (**ptrarr) = %c"**ptrarr);
    printf("\n ptrarr의 2차 참조 문자열 (*ptrarr) = %s \n\n"*ptrarr);
 
    return 0;
}

cs

 

실행 결과

 

 

 

 

line 10 까지 실행되면, 메모리 구조는 아래와 같다.

 

 

 

 

line 13 까지 실행되면, dptr도 ptrarr이 가리키고 있는 포인터 배열의 주소를 가리킨다.

 

파란색 박스는, 실제 메모리 구조는 아니지만, 이해하기 쉽게 하기 위해 그림.

 

 

 

배열명 = 포인터처럼

포인터 배열도 이중 포인터처럼 사용 가능하다.

 

코드 실행 결과에서 확인 가능하다.

 

ptrarr의 값 = dptr의 값 = ptrarr[0]의 시작 주소
*ptrarr = *dptr = ptrarr의 값 = Seoul문자열의 시작 주소

 

포인터는 복잡한 설명보다는, 메모리 구조를 직접 그려보며 이해 하는것이 좋다.

 

 

 


 

 

 

재귀호출

 

내용 정리

 

 

※ 재귀호출
함수가 자기 자신을 호출하여 순환하여 수행되는 것

 

재귀호출을 사용하면 프로그램을 간단하게 작성할 수 있는 이점이 있다.

같은 유형의 하위 작업이 필요할 때 사용한다.

 

 

한 번에 해결할 수 있는 가장 작은 단위의 하위 작업을 베이스케이스라고 한다.

 

 

베이스케이스를 잘 정의하고, 재귀호출이 베이스케이스를 향하게 코딩해야 한다.

 

 

재귀호출 함수를 가장 잘 보여주는 팩토리얼 문제를 확인해보자.

 

 

예제 2-14 재귀호출을 이용해 팩토리얼 값 구하기

 

 

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
#include <stdio.h>
 
unsigned int fact(int);
 
int main()
{
    int n, result;
 
    printf("정수를 입력하세요: ");
    scanf("%d"&n);
    result = fact(n);
    printf("\n\n %d의 팩토리얼 값은 %d입니다.", n, result);
 
    return 0;
}
 
unsigned int fact(int n)
{
    int value;
    if (n <= 1)
    {
        printf("\n fact(1)함수 호출!");
        printf("\n fact(1)함수 반환!");
        return 1;
    }
    else
    {
        printf("\n fact(%d)함수 호출!",n);
        value = (n * fact(n-1));
        printf("\n fact(%d) 값 %d 반환!", n,value);
        return value;
    }
}
cs

 

 

재귀함수인 fact 함수에서 

 

베이스케이스는 n <= 1 인 경우이다.

 

나머지의 경우는 베이스케이스를 향해 함수를 반복 실행한다.

 

 

 

실행 결과

 

 

실행결과를 참고하면 재귀호출의 기본적인 원리를 알 수 있다.

 

 

재귀함수는 함수 실행 중 내부 함수 실행

 

내부 함수 실행 중 또 내부 함수 실행

 

이때, 베이스 케이스를 만나면 

 

마지막에 실행됐던 함수부터 리턴이 되는 방식이다.

 

그림으로 표시하면 아래와 같은 순서로 코드가 흘러간다.

 

 

 

다른 대표적인 예로 하노이탑 문제가 있는데, 생략하겠다.