F.R.I.D.A.Y.

배열(array) part2. 다차원 배열 본문

DEV/C C++

배열(array) part2. 다차원 배열

F.R.I.D.A.Y. 2020. 1. 20. 23:39
반응형

Prev. 

 

배열(array) part1. default

이전 포스트[# 한참 지난 포스트이긴 하지만..\n 한참 시간이 지난 포스트다 보니 설명하는 어투가 다릅니다. 대표적으로 존댓말로 바뀌었다던지.. 아마도 조만간 개편을 진행해야겠군요.]에서 우리는 자료형과..

pang2h.tistory.com

 배열의 심화 학습이라고 생각할 수 있는 포스트입니다. 이전 시간에는 배열의 기본적인 사용법을 알아보았다면 이번 시간에는 다차원 배열에 대해 알아봅니다.


차원

 먼저 작성되었던 포인터에서도 언급이 되었던 차원 개념입니다. 우리 세계는 3차원 공간에 1차원의 시간이 더해진[# 뭐 더 나아가면 더 많은 차원이 존재한다는 말도 있지만] 시공간이라고 말합니다.

 우리가 점을 표현할 때는 몇 차원이 필요할까요? 차원이 필요하지 않습니다. 정적인 것이기 때문이죠. 선은 1차원, 면은 2차원, 입체는 3차원이 필요한 도형이라고 말합니다.

 

 이러한 차원의 개념을 배열에도 적용한 것이 바로 다차원 배열입니다.

 

다차원 배열

 이전 포스트에서 설명했던 배열은 단순히 정적인 점이라 할 수 있는 요소들의 집합을 모아놓은 것이라 설명할 수 있겠습니다.

 그러나 다차원 배열은 포함되는 각각의 요소 자체가 배열인 자료형입니다. 요소로 되는 배열은 1차원 배열[# 대괄호 연산자를 하나만 이용해 선언한 배열. 이전 포스트에서 다루었던 배열이 1차원 배열이라고 부릅니다.]이 아닌, 2차원 이상 n-1차원[# 이때 n은 부모 배열의 차원] 배열이 될 수 있습니다.

 

 다차원 배열은 다음과 같이 선언할 수 있습니다.

int arr[m][n];

// m, n: 요소의 수

 위 코드는 n개의 요소를 가진 배열이 m개가 모여 구성된 다차원 배열 변수를 선언한 것입니다. 이차원 배열만 작성할 수 있는 것이 아니라 대괄호 연산자를 사용한 개수만큼 차원을 크게 해 선언하는 것이 가능[# 그러나 무작정 차원을 크게 하는 것은 지양하세요. 우리가 다루는 자료의 대부분은 2차원을 다루게 될 것입니다. 껏 해봐야 3차원도 자주 사용하지 않습니다. 만일 본인의 코드에서 3차원 이상의 배열을 사용한다면 다시 한번 생각해보세요.]합니다.

 

초기화 문법

 또한 초기화 문법도 아래처럼 지원합니다. 단일 중괄호 쌍을 이용할 수도, 차원에 맞추어 중괄호 쌍을 이용할 수도 있습니다.

// CASE 1
int arr[m][n] = {
     {0,1,2,3, ...},
     ...,
     {0,1,2,3, ...}
    };

// CASE 2
int arr[m][n] = {0,1,2,3,...};
더보기

# 초기화 방법은 혼용이 가능합니다.

 다섯 줄의 배열이 있고 각 배열의 요소 길이가 10인 경우 아래와 같이 초기화가 가능합니다.

int arr[5][10] = {
    {0,0,0,0,0},
    {1,2,3,4,5,6,7},
    1,2,3,4,5,6,7,8,9,17,11,12,13,14
};

 초기화 데이터를 담는 첫 중괄호 안에 존재하는 여러 개의 중괄호 쌍[# { {}, {} }]은 다섯 개의 배열에서 순서대로 0번 인덱스의 배열을 의미합니다. 중괄호로 써지지 않은 데이터들은 일차원 배열에서의 초기화와 마찬가지로 해당하는 인덱스 요소의 초기화 값을 의미합니다. 이 코드를 가지로 초기화를 진행할 경우 아래와 같은 결과가 나오게 됩니다.

https://www.onlinegdb.com/online_c_compiler
// 출력 코드
#include <stdio.h>

int main()
{
    int arr[5][10] = {
        {0,0,0,0,0},
        {1,2,3,4,5,6,7},
         1,2,3,4,5,6,7,8,9,17,11,12,13,14
    };

    for(int i = 0 ; i < 5;++i){
        for(int k= 0; k < 10; ++k){
            printf("%2d ", arr[i][k]);
        }
        printf("\n");
    }

    return 0;
}

 거기에 더해 일차원 배열의 선언 방법과 마찬가지로 가장 처음 작성하는 대괄호는 명시적을 값을 작성하지 않고 비워둘 수 있습니다. 아래처럼 말이죠.

int arr[][10] = {
    {0,0,0,0,0},
    {1,2,3,4,5,6,7},
    1,2,3,4,5,6,7,8,9,17,11,12,13,14
};

 이렇게 하면 컴파일러가 네 줄[# 중괄호로 감싸진 것 둘과 감싸지지 않은 열네 숫자가 들어갈 공간. 열 네 숫자를 넣을 수 있는 길이 10인 배열의 수는 두 개 입니다.]이라고 판단하여 빈 대괄호에 4를 작성해 컴파일을 진행합니다. 그 외 삼차원 배열 등에서도 처음 나오는 대괄호 외에는 전부 숫자를 작성해주어야 합니다. 컴파일러가 길이를 몇으로 잡아야 할지 모르니까요 :)


실습하기

 어느 학급에 8명의 학생이 존재합니다. 이 학생들의 다섯 가지 과목의 점수를 입력하려고 합니다. 그래서 각 과목으로 점수를 묶어서 관리하기 위해 배열 다섯 개를 만들었습니다.

kor부터 sci까지 다섯 개의 배열 생성

 코드로 보면 아래와 같겠군요.

#include <stdio.h>

int main(void){
    int kor[8];  // korean
    int eng[8];  // english
    int math[8]; // math
    int soc[8];  // society
    int sci[8];  // science

    for(int i = 0; i< 8; ++i){
        scanf("%d %d %d %d %d", kor+i, eng+i, math+i, soc+i, sci+i);
    }

    for(int i = 0; i< 8; ++i){
        printf("%d번 점수: %d %d %d %d %d\n",i+1, kor[i], eng[i], math[i], soc[i], sci[i]);
    }

    return 0;
}

 무리 없이 작동할 코드이겠지만 늘 말씀드리는 것처럼 프로그래머는 효율적인 코드를 만들어야 합니다. 그런 면에서 이 코드는 비효율적이라 말할 수 있겠습니다. 이런 때에는 다차원 배열을 사용하는 것이 좋겠습니다.

 

다차원 배열 사용하기

 8명이 각자 5개의 데이터를 가지고 있습니다. 첫 번째로 사람 수만큼의 공간이 필요하고, 둘째로 각 인물이 가지고 있는 데이터를 보관할 공간이 필요합니다.

int student[8][5];

 그러고 나서 반복문을 통해 값을 입력받아줍니다.

for(int i = 0; i<8;++i){
    scanf("%d %d %d %d %d", student[i] + 0, student[i] + 1, student[i] + 2
                          , student[i] + 3, student[i] + 4);
}

 이렇게 작성하면 한 인물의 데이터를 받아낼 수 있습니다. 그러나 몇 번 인덱스가 어떤 값을 의미하는지 잘 모르겠습니다. 한 번 값의 속성을 결정하고 프로그래밍을 진행하면 해당 인덱스는 특정 데이터로 고정된다고 생각[# 쉽게 생각해서 일기장으로 쓰던 공책은 계속 일기장으로, 가계부로 쓰던 공책은 계속 가계부로 사용하는 것]할 수 있습니다. 그렇다면 우리는 전처리 구문을 이용해 [0 ~ 4]의 값에 의미를 부여할 수 있습니다.

#define KOREAN  0
#define ENGLISH 1
#define MATH    2
#define SOCIETY 3
#define SCIENCE 4

 이렇게 전처리 구문을 작성했다면 우리는 반복문 내의 코드를 아래와 같이 수정할 수 있습니다.

for(int i = 0; i<8;++i){
    scanf("%d %d %d %d %d", student[i] + KOREAN, student[i] + ENGLISH, student[i] + MATH
                          , student[i] + SOCIETY, student[i] + SCIENCE);
}

 상수가 아닌 단어로 표현되기 때문에 마치 구조체의 멤버 변수를 이용하듯 사용할 수 있게 됩니다.


더 읽어보기

 

배열 선언을 x-y가 아니라 y-x순으로 작성하는 이유

이전 마방진 포스트에서 배열 선언은 x-y가 아니라 y-x순으로 작성하는 것이 효율적이라고 말씀드린 적이 있습니다. 오늘은 어째서 y-x순이 더 효율적인지에 대해 포스트합니다. 홀수 마방진 풀기 이웃 학부에서..

pang2h.tistory.com

 

포인터 배열? 배열 포인터?

모든 자료형은 배열로 만들 수 있습니다. 그리고 동시에 포인터로 가리킬 수 있죠. 이번 시간에는 자주 헷갈리는 문법, 포인터 배열과 배열 포인터를 알아봅니다. 배열 배열 속에 들어있는 각 요소의 자료형은 배..

pang2h.tistory.com

 

포인터와 배열

배열 변수의 이름이 0번 인덱스의 시작 주소인 이유 이번 포스트는 제목 그대로 배열 변수의 이름이 어째서 해당 배열의 0번 인덱스의 주소가 되는지 알아봅니다. 간단해요! int arr[10]; &arr[0]; // 처음 배울..

pang2h.tistory.com

# index

728x90
반응형

'DEV > C C++' 카테고리의 다른 글

포인터와 배열  (0) 2020.01.24
Designated Initializer  (0) 2020.01.21
배열(array) part1. default  (1) 2020.01.19
포인터(pointer) part2. 다차원 포인터  (0) 2020.01.17
CallByValue vs CallByReference  (0) 2020.01.09
Comments