티스토리 뷰

C, C++

[ C언어 ] 12. 배열

RiKang 2017.11.25 00:40

Table of Contents


개요

배열의 선언

배열에 있는 변수 사용하기

문제

메모리에 저장된 배열

주의할 점

다차원 배열




1. 개요


 예를 들어, 정부에서 일하는 한 프로그래머가 대한민국 모든 성인의 키를 저장해야 한다고 해보겠습니다. 키를 저장하려면 실수형 변수에 저장 시켜야 할 것입니다. 그런데 만일 실수형 변수 5000만개를 따로 따로, double height1, height2, height3, ..., height50000000 이런 식으로 선언해서 사용한다고 생각해보면 앞길이 막막해 집니다. 하지만 걱정하지 않으셔도 됩니다. 다행히 C언어에는 같은 변수형의 변수들을 하나로 묶어서 한 방에 선언하는 방법이 있으니까요. 바로 배열(Array)입니다.




2. 배열의 선언


 배열 선언의 기본 예시는 아래와 같습니다.


1
2
3
4
5
6
7
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
    int a[5]={4,2,3,1,2};
    char b[5];
    return 0;
}
cs


 변수유형 배열이름[변수개수] = {첫 번째 변수의 초기값, 두 번째 변수의 초기값, ..., 마지막 변수의 초기값 };


 이렇게 선언하면 지정한 초기값이 들어가 있는 변수들이 생성됩니다. 위의 예시에서는 int형 변수 5개, char형 변수 5개가 선언되었으며 int형 변수에는 각각 4, 2, 3, 1, 2의 값이 들어가 있습니다.


 변수유형 배열이름[변수개수];


 초기값을 넣어줄 필요가 없다면 이런 식으로 선언도 가능합니다. 변수 개수는 숫자 혹은 상수를 이용해서, 딱 정해진 수를 넣어주어야 합니다.


1
2
3
4
5
6
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
    int a[5]={4,2,3,};
    return 0;
}
cs


 이런 식으로 초기값을 앞부분만 설정하고 뒤는 ',' 하나 만을 남긴 채 뒤를 생략해도 에러가 나지 않습니다. 대신 그 뒤의 변수들은 모두 0으로 초기화됩니다.


1
2
3
4
5
6
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
    int a[5]={0,};
    return 0;
}
cs


 따라서 이렇게 하면 모든 배열 안의 변수에 0이 들어가게 됩니다. 보통 모든 배열 안의 변수를 0으로 초기화하는 경우가 많기 때문에 이 점을 유용하게 사용할 수 있습니다.




3. 배열에 있는 변수 사용하기


 배열이름[숫자] 의 형태로 쓰면 지금까지 변수를 썼던 것과 똑같이 사용할 수 있습니다. 이 숫자에는 0 부터 배열크기-1 까지 들어갈 수 있지요. 우리나라는 일상적으로 1부터 시작하는 경우가 많기 때문에 이 부분에 위화감이 들 수 있지만, 배열 안의 변수에 붙이는 번호는 0번부터 시작합니다.


 예를 들어, a[0] 은 a 배열의 첫 번째 변수, a[1] 은 a 배열의 두 번째 변수를 나타냅니다. 아래의 프로그램을 통해 확인해 볼 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
    int a[5]={4,2,3,1,2};
    printf("%d\n",a[0]);
    printf("%d\n",a[1]);
    printf("%d\n",a[2]);
    printf("%d\n",a[3]);
    printf("%d\n",a[4]);
    return 0;
}
cs


출력 : 4 2 3 1 2


 배열을 사용할 때 편리한 점은, 배열이름[정수형 변수] 의 형태로 변수를 쓸 수 있다는 것입니다. 따라서 아래와 같은 프로그램도 같은 결과가 나옵니다.


1
2
3
4
5
6
7
8
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
    int a[5]={4,2,3,1,2};
    for(int i=0; i<5; i++)
        printf("%d\n",a[i]);
    return 0;
}
cs


출력 : 4 2 3 1 2


 결과 값이 정수로 나오기만 한다면 배열이름[수식] 의 형태도 가능합니다.


1
2
3
4
5
6
7
8
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
    int a[5]={4,2,3,1,2};
    for(int i=0; i<5; i++)
        printf("%d\n",a[4-i]);
    return 0;
}
cs


출력 : 2 1 3 2 4

 이렇게 하면 i=0 일 때 a[4], i=1 일 때 a[3] 처럼 역순으로 잘 출력 됨을 알 수 있습니다.


1
2
3
4
5
6
7
8
9
10
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
    int a[5];
    for(int i=0; i<5; i++)
        scanf("%d",&a[i]);
    for(int i=0; i<5; i++)
        printf("%d\n",a[i]);
    return 0;
}
cs


 또한 당연하게도 scanf 를 이용해 a[i]를 입력 받을 수 있습니다. 이제 아래의 문제들을 풀어보면서 직접 배열을 써먹어 보도록 하겠습니다.




4. 문제


백준 온라인 저지 채점 방법


(0) [BOJ 10039] 평균 점수


(1) [BOJ 2562] 최대값


(2) [BOJ 10801] 카드게임


(3) [BOJ 2587] 대표값2


풀이 모음




5. 메모리에 저장된 배열


 int a, b, c;를 선언했다고 해보면, 다음과 같이 메모리 상에서 떨어져 있을 수 있습니다.




 하지만 배열로 선언한 변수들은 메모리 상에 연속적으로 할당됩니다. int a[3]; 를 선언하면 아래와 같이 메모리에 서로 붙어서 할당됩니다.

.


컴파일러는 배열의 이런 특징을 이용하여 변수이름[숫자] 만으로도 빠르게 변수를 찾아 사용할 수 있는 것입니다.




6. 주의할 점


 배열이름[숫자] 의 형태를 사용할 때, 이 숫자에는 꼭 0 이상, 배열크기-1 이하의 정수가 들어가야 합니다. 실수형 변수에 정수를 넣었다고 해도 에러가 발생합니다. 


1
2
3
4
5
6
7
8
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
    int a[5]={1,2,3,4,5};
    double idx = 3;
    printf("%d\n",a[idx]); //에러!
    return 0;
}
cs


 이 프로그램을 돌려보면 에러를 확인할 수 있습니다. double 은 실수형 변수이기 때문에 정수형 변수와 숫자를 저장하는 방식 자체가 다릅니다. 따라서 아무리 3을 넣어주어도 에러를 피할 순 없습니다.


 이외에도 변수 i 가 0이 될 가능성이 있는 상황에서 a[i-1] 을 호출하는 등의 실수도 가능하며 이런 실수들은 생각보다 많이 보이는 실수들이므로 유의하는 것이 좋습니다.




7. 다차원 배열


 위에서 예시로 든 배열은 모두 1차원 배열입니다. 하지만 이 밖에도 2차원 배열, 3차원 배열, 4차원 배열등이 모두 가능합니다.


1
2
3
4
5
6
7
8
9
10
11
12
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
    int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
    for(int i=0; i<3; i++){
        for(int j=0; j<3; j++){
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
    return 0;
}
cs


 위는 2차원 배열의 예시입니다. 초기값을 넣어주려면 위와 같이 {배열, 배열, 배열} 의 형태를 취해야 합니다. 배열들의 배열이기 때문입니다. 사용은 1차원 배열과 대동소이합니다.


a[i][j] = i 번째 1차원 배열j 번째 변수이지요. ( 0 번째부터 시작합니다)


배열 a

 1

 2

 3

 4

 5

 6

 7

 8

 9


 2차원 배열을 위와 같이 테이블로 상상한 후, i 번째 행의 j 번째 열에 들어있는 값으로 편하게 생각해도 됩니다.


 3차원 배열의 경우도 똑같이 int a[5][5][5]; 로 선언하고 a[i][j][k] 로 가져다 쓰면 됩니다.


1
2
3
4
5
6
7
8
9
10
11
12
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
    int a[9]={1,2,3,4,5,6,7,8,9};
    for(int i=0; i<3; i++){
        for(int j=0; j<3; j++){
            printf("%d ",a[i*3+j]);
        }
        printf("\n");
    }
    return 0;
}
cs


 그런데 사실 위와 같이 2차원 배열은 1차원 배열로도 모두 처리할 수 있습니다. [3][3] 2차원 배열을 [3*3] 1차원 배열로 만든 후, [i][j] 를 사용하고 싶다면 [i*3+j] 를 사용하는 식이지요. 하지만 이런 방식은 코드를 복잡하게 만들게 됩니다. 다시 말하자면 2차원, 3차원, 4차원... 등등 다차원 배열은 일차원 배열로 불가능한 것을 가능하게 하려고 존재하는 게 아니라 프로그래머의 편의를 위해 존재하는 문법입니다.




'C, C++' 카테고리의 다른 글

[ C언어 ] 14. 문자열  (0) 2017.12.04
[ C언어 ] 13. 연산자 우선순위  (0) 2017.11.27
[ C언어 ] 12. 배열  (0) 2017.11.25
[ C언어 ] 11. 이진수와 비트연산자  (0) 2017.11.23
[ C언어 ] 10. 다중 반복문  (0) 2017.11.22
[ C언어 ] 9. 변수와 상수  (0) 2017.11.20