눈으로 하는 코딩이 아닌! 직접 타이핑하는 코딩은 실력 향상에 엄청난 도움이 됩니다.




안녕하세요~! 정선생이예요. 이번에는 함수 이후에 다뤘어야했던 변수의 유효범위를 알아볼거예요.

제가 작성한 줄 알고 넘어가는 바람에 게시글 순서가 살짝 꼬였네요.. 죄송합니다 ( __ )

일단 이 글은 배열 전에 읽어주시기를 바라고 함수 - 재귀함수 게시글을 보신 후에 보시는 것을 추천드립니다.

이전 게시글 보기 => ( 함수 ) ( 재귀함수 )



변수에 대해서는 두가지 종류가 있어요. 전역 변수와 지역 변수.

함수 외부에 변수를 정의 한 것은 전역 변수, 함수 내부에 변수를 정의 한 것은 지역 변수라고 해요.

글로는 주절주절 쓴 것 밖에 안되니까 바로 예제를 확인해보죠.


#include <stdio.h>
int x = 20;
int main() {
	printf("main block에서의 현재 x의 값 => %d\n", x);
	if(true){
		int x = 5;
		printf("if block에서의 x의 값 => %d\n", x);
	}
        int x = 10;
	printf("main block에서의 현재 x의 값 => %d\n", x);
	return 0;
}

결과값을 보시기 전에 미리 예측 해보고 하시는걸 추천합니다.


결과값을 보셨나요? ' 컴파일러는 각 블록에 있는 변수를 우선적으로 쓰게 된다. '

음.. 말이 어렵나요? 어떠한 변수를 쓰게되면 자신의 블록을 최우선으로 먼저 봅니다. 그런데 자신의 블록에 해당 변수가 없다면 그 상위 블록으로 나가서 확인을 해요.

2번째 줄의 int x = 20; 이 전역변수예요.

전역 변수와 지역 변수 차이점 중 하나가 지역 변수는 처음에 초기화를 해주지 않는다면 쓰레기 값이 생기는 반면, 전역 변수는 처음에 초기화를 해주지 않는다면 보통 0으로 자동 초기화가 됩니다.

int x = 20; 을 int x; 로 바꾸고 실행해보세요.


그리고 다음 예제를 봐보죠.


#include <stdio.h>
int main() {
	if(true){
		int x = 5;
		printf("if block에서의 x의 값 => %d\n", x);
	}
	printf("main block에서의 현재 x의 값 => %d\n", x);
	return 0;
}

아마 printf("main block~~") 줄이 에러가 날꺼예요. 왜냐면 현재 블록에서는 x가 없고, 그 상위 블록에도 x가 없으니까요.

" 아! 지역 변수가 해당 블록을 떠나면 사용 할 수 없구나. "

이해 되시나요?ㅎ



'Programming > C' 카테고리의 다른 글

[C] 배열(Array)  (0) 2018.05.24
[C] 재귀함수(Recursion)  (0) 2018.05.22
[C] 함수  (0) 2018.05.15
[C] 반복문  (0) 2018.05.06
[C] 조건문  (0) 2018.05.04


눈으로 하는 코딩이 아닌! 직접 타이핑하는 코딩은 실력 향상에 엄청난 도움이 됩니다.




안녕하세요~! 정선생이예요. 앞서했던 내용들은 C의 기초였어요. 앞으로는 좀 더 심화된 내용을 다룰꺼예요.

그 심화된 내용의 첫 번째. 바로 배열(Array)입니다.

정말 단순하게 '둘 이상의 변수를 모아둔 것'을 배열이라고 해요. 그런데 변수들과는 다르게 선언법과 접근법이 달라요. 


배열이 왜 필요하게 됐는지가 중요하겠죠?

초등학교로 예를 들어볼게요. 각 학년별 반(class) 인원을 저장하는 변수들이 필요하다고 생각해보죠.


우선 1학년만 10개의 반이 있다고 가정할게요. 

int class101, class102, class103, ...;

선언하는 것도 한세월이 걸리겠네요..

그런데 이걸 한 번에 해결해주는게 배열이예요.


배열의 선언법은 간단합니다.

데이터타입 배열명[배열의길이];

즉, [    int   class1[10];    ]. 

이 말은 다음 그림 예시와 같아요.



간단하게 number[5]는 5개의 방을 가졌고. 0호 방, 1호 방, 2호 방, 3호 방, 4호 방이 있다. 라고 생각하면 더 편합니다.

그런데 이 방은 int형이다.. 정도?

배열은 메모리 주소에 연속되서 적재되요. 적재된다는 얹어진다고 보면 되요.


 메모리 주소

(Byte 단위)

내용 

 1000

number[0] 

 1001

 1002

 1003

 1004

 number[1]

 1005

 1006

 1007


이런식으루요 ㅎㅎ 4바이트인 이유는 int형이기 때문!


배열의 선언만 알아서는 안되겠죠. 초기화를 알아야합니다.

초기화 방법은 다음과 같이 몇가지가 있어요.

 방법 1.

int arr[] = { 1, 2, 3, 4, 5 }; // arr[0]에는 1, arr[1]에는 2, ... , arr[4]에는 5가 차례대로 대입되면서 5개의 길이를 가진 배열임을 알게됨.

 방법 2.

int arr[5] = { 1, 2, 3, 4, 5 }; // 길이가 5인 배열을 만들면서 그 배열 속에 1~5까지 넣음.

 방법 3.

int arr[5]; // 길이가 5인 배열이 만들어짐

int i;  // 반복문을 돌면서 0번~4번 배열에 1, 2, 3, 4, 5를 대입.

for(i = 0; i < 5; i++)

    arr[i] = i + 1;


출력은 각각의 방 번호(인덱스라고 합니다)를 직접적으로 넣으면 됩니다.

[      printf("%d", arr[4]);     ] 처럼 말이죠ㅎㅎ 물론 상수가 넣어져있는 변수에도 가능해요.

[      printf("%d", arr[n]);     ] 처럼요.


주의할 점은 해당 배열의 길이를 넘어서면 안됩니다. 다른 메모리를 건드려 시스템이 맛탱이가 갈수도 있어요 :( 진짜 가장 중요합니다.



초기화 방법에 출력방법까지 알았겠다.. 그렇다면 이제 활용을 해봐야겠죠?

1~10이 저장되어 있는 배열에서 사용자가 입력한 숫자를 찾는 예제가 가장 적합해보여요. 소스를 봐보죠.


#include <stdio.h>

int main() {
    int arr[10] = { 2, 3, 1, 4, 7, 5, 8, 6, 10, 9};
    int n;
    int i;
    scanf("%d", &n);
    for(i = 0; i < 10; i++){
        if(arr[i] == n){
            printf("찾음!\n");
            break;
        }
    }
    if(i == 10)
        printf("못찾음!\n");
    return 0;
}

배열을 초기화 한 후에 입력을 받네요.

i = 0 ~ 9까지 1씩 증가하면서 arr[i]의 값과 n을 비교하네요. 같으면 찾는 값이니 '찾음!'을 출력하고, 아무것도 못 찾고 for문을 빠져나오면 i는 10이겠죠?

그러니 못찾음이 출력되고 끝납니다. ㅎ 이해 되시나요?  ㅎ


" 쌤 그러면 정렬도 가능하겠네요?! "

 => 당연히 가능합니다. 다음 게시글에서 정렬을 다루게 될 예정이예요. 혹여나 못 다루게 되면 그 다음 게시글에 꼭 다룰거예요.



다음으로 다차원 배열이라는게 있어요.

2차원 배열, 3차원 배열이 대표적이고 보통은 2차원 배열까지만 쓰죠.

2차원 배열은 여러개의 1차원 배열이 합쳐진거라고 보면되요.

다시말해서..

int arr[3][5]; 라고 치면은

arr[5] 라는 배열이 3개가 더 있는거예요

즉 다음과 같은 느낌으로 배열이 표현이 되겠죠?


arr[0][0]

arr[0][1]

arr[0][2] 

arr[0][3] 

arr[0][4] 

arr[1][0]

arr[1][1] 

arr[1][2] 

arr[1][3] 

arr[1][4] 

arr[2][0]

arr[2][1]

arr[2][2]

arr[2][3]

arr[2][4] 


행렬로 표현이 된다고도 하죠?

그렇지만 메모리에는 일자로 되있겠죠? 메모리가 행렬처럼 2차원적으로 존재하지는 않으니까요 ㅎ


arr[0][0]

arr[0][1] 

arr[0][2] 

arr[0][3] 

arr[0][4] 

arr[1][0] 

... 

... 

... 

... 

... 

... 

... 

... 

arr[2][4] 


이렇게 저장이됩니다 :) 이건 언제 쓰냐구요?? 음.. 아까 학급에 대한 예를 계속 들어보도록하죠!


각 학년별로 학급은 10개 반이라고 치면,

1학년 10개, 2학년 10개, 3학년 10개, ... , 6학년 10개. 총 60개의 인원 저장 변수가 필요해요.

그렇다면 arr[60]으로 해도 되겠죠?

그치만 조금 더 가독성있게, 보는 사람도 편한 느낌이 들게 정의해보자구요.

arr[6][10];

arr[0][?] 라인은 1학년

arr[1][?] 라인은 2학년

...

arr[5][?] 라인은 6학년.

오히려 접근성이 편하겠죠? 이해하기도 쉽구요.


이차원 배열에 대한 접근이나 초기화는 반복문을 중첩해서 합니다. 다음과 같이요.

#include <stdio.h>

int main() {
   int arr[6][10];
   int i, j;
   int num=1;
   for(i = 0; i < 6; i++){
      for(j = 0; j < 10; j++)
         arr[i][j] = num++; 
   }
   for(i = 0; i < 6; i++){
      for(j = 0; j < 10; j++)
         printf("%d ", arr[i][j]);
   }
    return 0;
}

" 쌤 아까 메모리에는 일자로 되어있다고 했는데 그러면 1차원 배열로 호출해도 되지 않나요? arr[1][0] 을 arr[10]처럼요!! "

 => 이 질문에 대해서는 다음의 코드를 작성해보도록 하죠!


#include <stdio.h>
int main() {
   int arr[6][10];
   int i, j;
   int num = 1;
   for (i = 0; i < 6; i++) {
      for (j = 0; j < 10; j++)
         arr[i][j] = num++;
   }
   for (i = 0; i < 60; i++) {
	printf("%d ", arr[i]);
   }
   return 0;
}

아마도 결과는 8자리정도 되는 숫자가 일정한 규칙으로 나올꺼예요. 다음처럼ㅎㅎ



결과처럼 나온 이유는, 현재 값이 얹어져있는 메모리 위치를 출력해준거예요. 그리고 일정한 규칙으로 커지고 있어요. 이건 2차원 배열 arr[6][10]에서 10의 숫자를 바꿔보면서 출력하면 제가 어떤 얘기를 하려했는지 알꺼예요. ^.^

그리고 조금 더 자세한 내용은 추후 포인터 부분에서 다룰꺼예요.

지금은 2차원 배열에서는 arr[i][j] 방식으로 출력한다를 꼭 지켜주시구요.



배열에 대한 내용은 앞으로 함수와 배열, 정렬에 대한 기초를 해드리고 배열 내용을 마치려합니다.







게시글을 보시다가 궁금한 내용, 이게 맞나? 하는 내용, 이건 틀렸어!하는 내용들은 과감하게 댓글 달아주시면 감사하겠습니다.


이론적인 내용에 대한 궁금증은 검색을 통해 궁금증을 해결하는 것이 좋아요!!

실습적인 내용에 대한 궁금증은 최대한 생각을 해보고 검색을 하는 것이 좋아요!!

'Programming > C' 카테고리의 다른 글

[C] 변수의 유효범위 ( 미완성 )  (0) 2018.05.29
[C] 재귀함수(Recursion)  (0) 2018.05.22
[C] 함수  (0) 2018.05.15
[C] 반복문  (0) 2018.05.06
[C] 조건문  (0) 2018.05.04


눈으로 하는 코딩이 아닌! 직접 타이핑하는 코딩은 실력 향상에 엄청난 도움이 됩니다.




안녕하세요~! 정선생이예요. 이번에는 재귀함수를 배워볼꺼예요.

일단 재귀함수의 사전적 정의를 봐보죠!! 재귀란, 수학이나 컴퓨터 과학 등에서 자신을 정의할 때 자기 자신을 재참조하는 방법을 뜻한다. (출처바로가기)

음.. 마지막이 중요해요. 자기 자신을 재참조한다. 프로그래밍에서는 자기 자신을 재호출한다. 로 바꿔서 해석할 수 있어요. 이게 뭔소린지 예제소스를 보면서 알아가봐요!!


가장 많은 예시로 사용되는 코드는 계승(Factorial)이예요. 표시는 n! 로 합니다. 자세히 들어가면 수학시간이 되버리니까 구글링으로 정의를 알아보도록해요 ㅎㅎ 자 일단은, 3! = 1 x 2 x 3 이구요. 5! = 1 x 2 x 3 x 4 x 5 가 됩니다.

" 아하! n! 이란 1~n 까지를 곱한거구나. "

이해 가시나요?

1~n까지 1씩 증가하면서 곱한 값을 출력해주는거니까 반복문으로 해결 할 수가 있겠죠?


#include <stdio.h>

int main() {
    int n=10;
    int i, fact=1;
    for(i = 2; i <= n; i++)
        fact = fact * i;
    printf("10! = %d", fact);
    return 0;
}

 출력

10! = 3628800


자 반복문으로 작성했으니 10!을 구하는 함수를 작성해봅시다.

#include <stdio.h>
int fact(int n){
    int i, result;
    result = 1;
    for(i = 2; i <=n) i++)
        result *= i;
    return result;
}

int main() {
    printf("10! = %d", fact(10));
    return 0;
}

이제 이 함수를 재귀함수로 바꿀수가 있는데요. 이게 쉽다고 단정을 짓기도 애매하고, 어렵다고 확정 짓기도 애매합니다.. 


일단 재귀함수란, 자기 자신을 계속 호출하는건데 어떤식으로 호출하는지 코드를 볼게요.

#include <stdio.h>
int fact(int n){
    if(n == 1)
        return 1;
    else
        return n * fact(n-1);
}

int main() {
    printf("10! = %d", fact(10));
    return 0;
}

코드는 생각보다 엄청 간결해졌어요.  fact함수는 매개변수로 정수형 변수 하나를 받네요.

맨 처음은 fact(10)

if에서는 false니까 넘어가겠죠?

그리고 return n * fact(n-1) 을 해주는데 현재 n은 10이죠?

그러면 fact(9)를 호출하겠네요. 그렇다면 return 10 * fact(9)

fact(9)에서는 9 * fact(8)

fact(8)에서는 8 * fact(7)

...

fact(2)에서는 2 * fact(1)

fact(1)에서는 if문의 true가 되니까 1을 리턴합니다.

자 그러면 계산된 값들을 역으로 올라가봅니다.

fact(1)은 1이니까 fact(2)에서는 2 * 1이 되요.

fact(3)에서는 3 * fact(2). 즉 3 * 2 * 1.

fact(4)는 4 * fact(3). 즉 4 * 3 * 2 * 1.

...

fact(9)는 9 * fact(8). 즉 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1.

fact(10)은 10 * fact(9). 



재귀함수는 여러 문제를 봐보면서 어떤 방식으로 동작하는지를 파악해야해요.

코드 자체를 외운다기보다는 공책 펴놓고 거기에서 n이 10일때, 9일때, 8일때, ... 각각의 n에 대해 함수가 어떻게 작동하는지를 디버깅 해보면 이해가 쉽게 될거예요. 컴퓨터 코딩이라고 손코딩이 중요하지 않은 것은 아니예요. 손코딩도 그만큼 중요합니다 ^.^



======================================== 5월 29일에 추가된 내용 ==========================================


현재 제가 작성 한 줄 알고 넘어갔던 변수의 유효범위와 관련된 게시글을 재귀함수 다음으로 읽어주시고 배열 파트로 넘어가시길 권장합니다.

죄송합니다 ( __ )

( 변수의 유효범위 게시글로 바로가기 )




게시글을 보시다가 궁금한 내용, 이게 맞나? 하는 내용, 이건 틀렸어!하는 내용들은 과감하게 댓글 달아주시면 감사하겠습니다.


이론적인 내용에 대한 궁금증은 검색을 통해 궁금증을 해결하는 것이 좋아요!!

실습적인 내용에 대한 궁금증은 최대한 생각을 해보고 검색을 하는 것이 좋아요!!

'Programming > C' 카테고리의 다른 글

[C] 변수의 유효범위 ( 미완성 )  (0) 2018.05.29
[C] 배열(Array)  (0) 2018.05.24
[C] 함수  (0) 2018.05.15
[C] 반복문  (0) 2018.05.06
[C] 조건문  (0) 2018.05.04

+ Recent posts