C언어 배열과 포인터 다차원 배열

    2018-02-07 01:49:18 작성

    2차원 배열

    2차원 배열은 평면구조의 배열입니다. (엑셀을 연상하시면 쉽습니다.)
    행과 열이 있는 배열구조입니다.

    2차원 배열의 선언은 형식은 다음과 같습니다.

    int arr[3][5] // 세로(행)길이 3, 가로(열)길이 5 인 int형 배열


    위의 그림과 같이 1행 = 1차원배열과 같고 1차원배열이 여러개 모여 2차원배열을 구성하게됩니다.
    2차원 배열의 접근은 [행의 인덱스값][열의 인덱스값] 과 같은 형태가 됩니다.
    아래의 코드는 arr[3][5]의 주소와 각각의 길이를 출력하는 프로그램입니다.

    #include <stdio.h>
    
    int main(void) {
    	int arr[3][5];
    
    	printf("arr       주소 : %p | 길이 : %d\n", arr, sizeof(arr));
    	printf("arr[0]    주소 : %p | 길이 : %d\n", arr[0], sizeof(arr[0]));
    	printf("arr[0][0] 주소 : %p | 길이 : %d\n", &arr[0][0], sizeof(arr[0][0]));
    	printf("arr[1]    주소 : %p | 길이 : %d\n", arr[1], sizeof(arr[1]));
    	printf("arr[1][0] 주소 : %p | 길이 : %d\n", &arr[1][0], sizeof(arr[1][0]));
    	printf("arr[2]    주소 : %p | 길이 : %d\n", arr[2], sizeof(arr[2]));
    	printf("arr[2][0] 주소 : %p | 길이 : %d\n", &arr[2][0], sizeof(arr[2][0]));
    	return 0;
    }


    전체 길이는 3 * 5 * 4 = 60이 되고
    arr[0] 행의 사이즈는 5 * 4 되어 20의 길이가 됩니다. arr[1], arr[2]도 같습니다.
    arr[0][0]은 int 자료형이므로 4byte 사이즈를 갖습니다.
    주소는 arr == arr[0] == arr[0][0]의 주소가 같습니다.
    arr[0]은 arr[0][0]에 대해 1차원 배열과 같고 배열의 이름은 상수 형태의 포인터 이기 때문에 주소를 전달함에 있어 &연산자를 붙이지 않습니다.
    arr[1]은 arr[0]의 주소로부터 20차이가 나고, arr[2]의 경우에도 arr[1]로 부터 20차이가 나고있습니다.


    2차원 배열의 선언 및 초기화 방법

    #include <stdio.h>
    
    void arrPrint(int (*arr)[5], int row, int col);
    
    int main(void) {
    	int arr[3][5] = {
    		{ 1, 2, 3, 4, 5 }, // 1행
    		{ 6, 7, 8, 9,10 }, // 2행
    		{ 11,12,13,14,15 }  // 3행
    	};
    
    	int arr2[2][5] = {
    		{ 1 },  // 1행 {1, 0, 0, 0, 0}
    		{ 5,6 } // 2행 {5, 6, 0, 0, 0}
    	};
    
    	int arr3[][5] = { 1, 2, 3, 4, 5, 6, 7, 8 , 9, 10, 11 };
    	// 1행 { 1, 2, 3, 4, 5 }
    	// 2행 { 6, 7, 8, 9,10 }
    	// 3행 {11, 0, 0, 0, 0 }
    
    	int i, j;
    	printf("arr\n");
    	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
    		for (j = 0; j < sizeof(arr[0]) / sizeof(arr[0][0]); j++) {
    			printf("%2d ", arr[i][j]);
    		}
    		printf("\n");
    	}
    
    	printf("\narr2\n");
    	for (i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++) {
    		for (j = 0; j < sizeof(arr2[0]) / sizeof(arr2[0][0]); j++) {
    			printf("%2d ", arr2[i][j]);
    		}
    		printf("\n");
    	}
    
    	printf("\narr3\n");
    	for (i = 0; i < sizeof(arr3) / sizeof(arr3[0]); i++) {
    		for (j = 0; j < sizeof(arr3[0]) / sizeof(arr3[0][0]); j++) {
    			printf("%2d ", arr3[i][j]);
    		}
    		printf("\n");
    	}
    	return 0;
    }


    arr 배열은 매우 일반적인 선언입니다.
    arr2 배열은 열과 행을 2,5로 지정하였고 일부만 선언했으며, 비어있는 값은 0으로 초기화 됩니다.
    arr3 배열은 1차원 배열을 초기화하는 형태로 되어있지만 아래 주석처럼 앞에서부터 배열을 채워나가며, 남는 요소는 0으로 초기화 됩니다.
    arr3 처럼 열정보는 생략이 가능하지만 행정보는 생략할 수 없습니다.


    3차원 배열

    3차원배열은 2차원 배열이 여러개 모인 입체 구조의 배열입니다.
    2차원 배열을 잘 이해하였다면 3차원 또는 그이상의 배열구조를 이해하실 수 있습니다.
    다음은 3차원 배열로 학급별 학생의 점수를 나타내 보았습니다.

    #include <stdio.h>
    
    int main(void) {
    	int i, j, k;
    	int arr[3][3][2] = {
    		{
    			{ 87,67 }, // 1학급 1번학생 점수
    			{ 74,85 }, // 1학급 2번학생 점수
    			{ 97,86 }  // 1학급 3번학생 점수
    		},
    		{
    			{ 90,83 }, // 2학급 1번학생 점수
    			{ 98,82 }, // 2학급 2번학생 점수
    			{ 60,75 }  // 2학급 3번학생 점수
    		},
    		{
    			{ 57,87 }, // 3학급 1번학생 점수
    			{ 99,95 }, // 3학급 2번학생 점수
    			{ 81,85 }  // 3학급 3번학생 점수
    		},
    	};
    
    	for (i = 0; i < 3; i++) {
    		double total = 0;
    		printf("%d 학급 : \n", i + 1);
    		for (j = 0; j < 3; j++) {
    			for (k = 0; k < 2; k++) {
    				printf("%2d ", arr[i][j][k]);
    				total += arr[i][j][k];
    			}
    			printf("\n");
    		}
    		printf("%d 학급의 평균점수 : %4.2f\n\n", i + 1, total / 6);
    	}
    	return 0;
    }


    arrPrint 함수에서 첫번째 인자의 int (*arr)[3][2]int arr[][3][2]은 같은 의미입니다.


    연습문제

    1. 8행 9열의 2차원 배열을 선언하고 2단 ~9단의 구구단을 저장합니다.
    2. 배열을 순회하며 다음과 같이 출력하세요.


    1. 5행 5열의 2차원 배열을 선언합니다.
    2. 이름 배열 char * names[4] = { "철수","영희","길동","소진" };
    3. 과목 배열 char * subject[4] = { "국어","영어","수학","과학" };
    4. 학생별로 과목 점수를 받습니다. 배열은 다음과 같은 값을 형태가 되도록 합니다.

    국어 영어 수학 과학 총점
    철수 89 76 84 74
    영희 77 85 92 91
    길동 78 65 80 68
    소진 95 89 87 94
    과목별 총점

    5. 개인별 총점, 과목별 총점, 전체총점을 구하여 배열에 저장합니다.
    6. 배열을 순회하며 출력합니다.