Coding & Programming/C언어 기초(A-Z)

[C언어 기초코딩: 예제로 간단 정리] 8.배열(array)

mainCodes 2021. 3. 14. 13:01

JollyTree의 C언어 기초코딩: 예제로 간단 정리 - 8. 배열(Array)

요약

- 배열의 개념, 배열의 선언과 초기화
- 함수 인수로서의 배열 사용 방법 그리고 n차 배열

 

안녕하세요 JollyTree입니다 (•̀ᴗ•́)و

지금까지는 단순히 개별적으로 int a;, char ch;, float b; 등과 같이 단일 변수를 사용하는 것을 정리했습니다. 배열은 이런 단일 변수를 동일한 자료형으로 여러개 붙여 놓은 것입니다. 배열을 공부하기 위해서는 메모리에 대한 이해가 조금 필요합니다.

 

이유는 동일한 타입의 데이터들은 메모리 내 연속된 공간에 배치되면 배열이 메모리 내에서 특정 주소를 부여받게 되는데 이 때 메모리 주소에 대한 개념을 이해하면 도움이 됩니다. 이 부분은 정리하면서 다시 언급하겠습니다.

 

- 배열(array) :  동일한 타입의 데이터가 여러개 저장되어 나열된 저장공간(메모리 공간)
  * 인덱스(index) :  배열 원소의 위치를 가리키는 것, 인덱스는 항상 0에서 부터 시작
  * 원소(Element) : 배열을 구성하는 하나하나의 값으로 인덱스를 이용하여 접근

 

아래 변수를 보면 일반적인 선언과 다르게 뒤에 대괄호 안에 숫자가 있는 것을 볼 수 있습니다. int는 자료형이고, number는 변수의 이름, 그리고 [10]은 배열의 크기 즉, 정수형을 5개 선언한 것입니다. 보통 원소(Element)라고 하며 배열의 크기를 5으로 선언했으니 배열의 원소가 5개라고 합니다. 이때 인덱스는 0부터 시작하니 0~4까지 5개가 됩니다.

 

int number[5];

 

컴퓨터의 메모리에는 아래와 같이 인덱스 0번째부터 4번째까지 순차적으로 저장됩니다. 이를 배열 number의 첫번째 원소는 number[0], 두번째 원소는 number[1]이라고 표현하고, 3번째 인덱스는 number[3], 4번째 인덱스는 number[4]라고 표현합니다.

 

int int int int int

※ 앞에서 부터 0번째로 시작해서 4번째칸까지 존재(number[0] ~ number[4])

 

배열이 없으면 아래와 같이 10개의 단일 변수를 선언해야 하는데, 소스코드 라인 수도 늘어나고 상당히 소모적인 방법입니다.


int number_1;

int number_2;

int number_3;

...

int number_5;

 

일반적인 배열의 선언예제입니다. 일반 변수 선언과 거의 유사하며 대괄호안에 크기를 지정해주는 것이 추가됩니다.

 

1차원 배열의 선언 예:

 

int english_subject[50];         //50개의 int형 값을 가지는 배열 english_subject

char name[256];                 //256개의 char형 값을 가지는 배열 name

float avg[20];                     //20개의 float형 값을 가지는 배열 avg

char addr[100], zipcode[100]; //100개의  char형 값을 가지는 배열 addr과 zipcode

 

배열의 원리를 파악하기 위해 먼저 간단한 예제를 작성해 보도록 하겠습니다.  아래 코드는 home_address라는 char 배열을 256의 크기로 선언하였습니다. 영어로 주소를 입력 받은 후 18라인의 for문을 이용하여 home_address[i]; 배열에 저장되어 있는 값을 인덱스(i변수) 0 ~ length까지 이동시키며 화면에 한글자씩 출력합니다.  그런 다음 다시 배열을 역순으로 length ~ 0의 인덱스까지 화면에 한글자씩 다시 출력합니다.

 

문자열(char) 배열 선언과 사용 예제:

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
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h> 
#include <string.h>
 
int main(void)
{
    //첫번째 예제
    char home_address[256];
    int length, i;
 
    printf("Please enter your home address in English: ");
    fgets(home_address, sizeof(home_address), stdin);
 
    length = strlen(home_address);
    printf("length = %d\n", length);
 
    //입력한 주소를 출력
    for (i = 0; i < length; i++)
        printf("%c", home_address[i]);
 
 
    //배열을 역순으로 출력
    for (i = length; i >= 0; i--)
        printf("%c", home_address[i]);
 
 
    printf("\n\n");
    
    return 0;
}
cs

 

아래는 실행결과 화면입니다. 입력한 문자열의 길이가 총 57자이니 0~56까지의 인덱스로 배열의 원소에 접근 할 수 있게됩니다. 

 

입력) 396, Gangnam-daero, Gangnam-gu, Seoul, Republic of Korea

3 9 6 ,   G a n ... a

정수형과 마찬가지로 첫번째 칸이 인덱스 0이며 마지막 a는 인덱스 56번째에 저장되어 있는 것입니다.

 

실행결과(Output):

그럼 정수형 배열 변수를 사용한 예제를 한번 살펴보겠습니다. 정수형 배열도 비슷합니다. 실행결과를 통해 알 수 있지만 정수형 배열 number는 총 10개의 정수형 원소를 가지고 있습니다. 0번째 인덱스에 있는 값은 11, 1번째 인덱스에 있는 값은 12 등의 값이 저장되어 있습니다. 12~13라인은 i를 이용하여 0부터 9까지의 인덱스를 증가시켜 총 10개의 배열 원소를 화면에 출력합니다.

 

그런 다음 17~18라인에서 number[1], number[2]의 값을 입력 받은 값으로 변경합니다.

 

정수형(int) 배열 선언과 사용 예제#1:

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
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
 
int main()
{
    //배열 초기화
    int number[10= { 11121314151617181920 };
    int i;
 
    printf("인덱스  값\n");
    printf("--------------------\n");
    for (i = 0; i < 10; i++) {
        printf("%d      %d\n", i, number[i]);
    }
    printf("\n");
    printf("변경할 number 변수의 두번째 원소와 세번째 원소의 값을 순서대로 입력하세요:");
    scanf("%d"&number[1]);
    scanf("%d"&number[2]);
 
    for (i = 0; i < 10; i++) {
        printf("%d      %d\n", i, number[i]);
    }
    printf("\n");
 
    return 0;
}
cs

 

실행결과를 보면 처음 초기화한 값하고 다르게 number변수 1번째 2번째 원소의 값이 새로 입력한 값인 5000과 6000으로 변경된 것을 알 수 있습니다. 

 

실행결과(Output):

 

정수형 배열의 두번째 예제입니다. 앞의 예제#1을 이해했다면 쉽게 이해할 수있는 예제로 5번째 라인과 41번째 라인은 함수의 인수로 배열 변수를 전달하여 배열을 복사하는 예제입니다.

 

정수형(int) 배열 선언과 사용 예제#2:

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
41
42
43
44
45
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define NUMBER_COUNT 3
 
int copyarrary(int score[])
{
    int i;
    int score_backup[3];
 
    //배열의 복사
    for (i = 0; i < sizeof(score)-1; i++)
        score_backup[i] = score[i];
 
    printf("배열을 복사하였습니다.\n");
 
    return 0;
}
int main()
{
    //세번째 예제
    int score[3];
    int sum = 0;
    int avg = 0;
    int i;
 
 
    for (i = 0; i < NUMBER_COUNT; i++)
    {
        printf("%d 번째(score[%d]) 학생의 영어 성적을 입력하세요 : ", i, i);
        scanf("%d"&score[i]);
    }
 
    for (i = 0; i < NUMBER_COUNT; i++)
        sum += score[i];
 
    avg = sum / NUMBER_COUNT;
    printf("영어 성적 합   = %d\n", sum);
    printf("영어 성적 평균 = %d\n", avg);
 
    //배열 복사 함수의 인수로 전달
    copyarrary(score);
 
 
    return 0;
}
cs

 

실행결과(Output):

 

다차원 배열

 

다차원  배열은 각 원소를 가리키는 인덱스가 여러 개입니다. 아래는 2차원 배열과 3차원 배열의 선언 예입니다.

 

int a[3][5];        //2차원 배열 선언 예

int b[3][4][5];    //3차원 배열 선언 예

 

2차원 배열은 각각의 원소를 가리키는 인덱스를 2개 사용합니다. 만약 int a[3][5];을 선언했다면 각 원소는 다음과 같이 접근할 수 있습니다. int a[3][5];에서 [3]은 '행'의 개수' 나타내며, 뒤의 [5]는 '열의 개수'를 의미하며 다음과 같이 2개의 인덱스를 사용하여 각각의 원소를 값을 쓰고 읽을 수 있습니다.

 

아래 표에서 세로는 '행(row)'을 나타내므로 3칸, 가로는 '열(column)'이라서 5칸 입니다. 인덱스 번호는 아래 칸에 표시하였으니 참고하세요.

a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]
a[1][0] a[0][1] a[0][2] a[0][3] a[0][4]
a[2][0] a[2][1] a[2][2] a[2][3] a[2][4]

 

배열은 선언과 동시에 초기화 할 수 있는데, 2차원의 배열의 경우 다음과 같이 초기화할 수 있습니다. 그리고 첫번째 인덱스를 생략해서 선언과 동시에 초기화를 할 수 있습니다.

 2차원 배열 선언 및 초기화 예

 int a[3][5] = {
    11, 12, 13, 14, 15,
    21, 22, 23, 24, 25,
    31, 32, 33, 34, 35
 }; 

 2차원 배열 선언 및 초기화 예

 int a[][5] = { 
    11, 12, 13, 14, 15,
    21, 22, 23, 24, 25, 
    31, 32, 33, 34, 35
 };
* 행(row)의 값 생략 가능

 

3차원 배열은 각각의 원소를 가리키는 인덱스를 3개 사용합니다. 3차원 배열은 입체적으료 표현되지만 깊이만 추가되었을 뿐 원리는 비슷하니다. int b[3][4][5]의 경우 맨 앞의 인덱스는 깊이, 두번째 인덱스는 행(4줄), 세번째 인덱스는 열(5칸)을 의미합니다. 첫번째 인덱스를 제외하고 생각하면 2차원 배열과 동일합니다. 

 

아래 예제는 2차원, 3차원 배열을 선언하고 모든 원소에 값을 넣은 후 다시 모든 원소를 화면에 출력하는 예제입니다.

 

2차원 배열, 3차원 배열 예제:

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
41
42
43
44
45
46
#include <stdio.h>
 
int main(void)
{
    int a[3][5]; 
    int b[3][4][5];
    int value = 0
    int i, j, k;
 
    //2차원 배열 값 저장
    for (i = 0; i < 3; i++)
        for (j = 0; j < 5; j++)
            a[i][j] = value++;
 
    //2차원 배열 값 출력
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 5; j++)
            printf("a[%d][%d] = %2d ", i, j, a[i][j]);
 
        printf("\n");
    }
 
 
    printf("\n");
    //3차원 배열 값 저장
    for (i = 0; i < 3; i++)
        for (j = 0; j < 4; j++)
            for (k = 0; k < 5; k++)
                b[i][j][k] = value++;
 
    //3차원 배열 값 출력
    for (i = 0; i < 3; i++)
    {
        printf("%d번째\n", i);
        for (j = 0; j < 4; j++)
        {
            for (k = 0; k < 5; k++)
                printf("b[%d][%d][%d] = %2d ", i, j, k, b[i][j][k]);
 
            printf("\n");
        }
    }
 
    return 0;
}
cs

 

실행결과(Output):

 

배열은 변수 하나로 많은 메모리 공간을 할당할 수 있고 정렬, 탐색, 버퍼링 등 다양한 용도로 활용할 수 있기 때문에 코딩할 때 정렬, 정말 많이 사용되는 문법입니다. 다른 언어에서도 유사한 문법이 있어서 알아두면 좋을 것 같습니다. 이상 JollyTree였습니다 (•̀ᴗ•́)و