티스토리 뷰

본 강좌는 아래 동영상 강좌와 같이 진행됩니다. 되도록이면 동영상과 같이 보시는 것을 추천합니다.

 

유튜브 채널 가기

 

강좌 12편 동영상 보기

 


 

 이번시간에는 같은 종류의 자료형 여러개를 한 묶음으로 관리할 수 있는 배열에 대해 알아보도록 하겠습니다.

 

 

 

 1. 배열의 선언과 초기화

 

 배열 (Array) 이란, 어떤 한가지 자료형을 연속적으로 나열하는 것을 말합니다. 만약 100명의 이름을 저장하여 사용하고자 한다면, 100개의 변수를 선언해서 각각 저장하고 사용해야 하는데, 배열을 사용하면 변수 하나로 아주 쉽게 사용할 수 있습니다.

 

선언을 할때는

 

자료형 변수이름[갯수];

 

 와 같이 사용하며, 아래와 같이

 

int a[5] = {1, 2, 3, 4, 5};

 

 int형 a라는 변수는 5개 만큼을 저장할 수 있는 배열로 선언되었고, 각각의 요소에 1, 2, 3, 4, 5를 저장하도록 초기화 되었습니다. 이런식으로 선언할 수 있고, 초기화는 중괄호 {}로 묶어 각각의 요소를 콤마로 구분하여 합니다.

 

 초기화 이외에 이렇게 사용해선 안됩니다.

 

int a[5];

a = {1, 2, 3, 4, 5};

 

 배열의 초기화는 변수를 선언할때처럼 생략하거나, 갯수보다 적은 수로 초기화 할 수 있습니다.

 

int a[5];

int b[5] = {1, 2};

 

 int형 배열 a는 초기값을 주지 않아 모두 쓰레기값이 들어가게 됩니다. 반면에 int형 배열 b는 자신의 크기보다 작은 갯수의 1, 2는 정상적으로 넣고, 그 이후는 0으로 초기화가 됩니다. 그래서 배열을 모두 0으로 초기화 하고자 할때에는

 

int a[5] = {0}; 

 

 이렇게 사용하는 것이 편리합니다.

 

또, 배열을 선언할때 다음과 같이 갯수를 지정하지 않고 쓰는 방법도 있습니다.

 

int a[] = {1, 2, 3};

 

 이렇게 사용하게 되면, a란 배열은 초기화된 값의 갯수만큼의 크기를 자동으로 가지게 됩니다. 그러나 다음과 같이

 

int a[];

 

 초기값을 정해주지 않으면 에러메시지를 만나게 됩니다.

 

 저의 경우 []와 같이 크기를 자동으로 지정하도록 사용은 잘 하지 않습니다. 그 이유는 배열의 크기가 커질수록 얼마인지 한눈에 파익하기 쉽지 않기 때문입니다. 편리한 만큼 리스크도 있다는걸 기억하고 계셨다가 적절하게 사용하시면 되겠습니다.

 

 그리고 배열을 선언할때 갯수를 변수로 넣을 수 없습니다.

 

int a = 5;

int b[a] = {0};

 

 위처럼 배열 b의 크기를 변수로 지정할 수 없고, 반드시 상수값으로 직접 숫자로 써 줘야 합니다.

 

 

 

 2. 배열의 사용

 

이제 선언된 배열을 사용해 봅시다.

 

int a[5] = {0};

 

 위와 같이 int형 배열 a의 갯수를 5개로 지정을 해주고 0으로 초기화를 해줬습니다. 여기에 각각 1, 2, 3, 4, 5를 넣어 보겠습니다.

 

a[0] = 1;

a[1] = 2;

a[2] = 3;

a[3] = 4;

a[4] = 5;

 

 이런 식으로 대괄호 [] 안의 숫자를 바꿔주면서 값을 넣어주면 됩니다. 이런 배열 전체가 아닌 'a[0]', 'a[1]'와 같은 것을 '배열의 원소' 라고 합니다.

 

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

 

 메모리상에는 이렇게 int형 변수가 나란히 붙어 있습니다. 선언을 할때는 갯수로 써주지만, 실제 사용을 할때에는 0부터 갯수만큼의 크기를 가지기 때문에 사용할때 주의하여야 합니다. 그리고, 이 각각의, 예를들어 'a[2]' 라는건 보통 int형 변수와 똑같이 사용할 수 있습니다.

 

 배열은 반복문과 사용될때 굉장히 편리합니다.

 

int a[5] = {1, 2, 3, 4, 5};

int i = 0;

 

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

printf("%d\n", a[i]);

 

실행 결과

 

1

2

3

4

5

 

 이런식으로 서로다른 이름의 변수를 사용할 때보다 소스코드가 간결해지고 편리해 집니다.

 

 지난 '문자열' 시간에 char형으로 문자열 변수를 선언했떤걸 기억하실 겁니다. 그것도 정확히 표현하자면 '문자열 변수' 가 아니라 '문자형 배열' 입니다.

 

char str1[10] = "abc";

char str2[10] = {'a', 'b', 'c'};

 

printf("%s\n", str1);

printf("%s\n", str2);

 

실행결과

 

abc

abc

 

 지난시간까지는 str1의 경우처럼 큰따음표 ""로 묶어 초기화를 해주고 사용했었습니다. 이것을 str2의 경우와 같이 일반 배열처럼 사용해도 결과는 같게 나오는걸 볼 수 있습니다. 하지만 '문자열형'이 없는 C언어이기 때문에 편의상 '문자형 배열'의 경우 큰따음표 ""로 초기화가 가능하게 만들어졌고, 프로그램내에서도 특별하게 다루는 것처럼 보일 뿐입니다. 

 

 

 

 3. 다차원 배열

 

 지금까지의 배열은 갯수가 하나인 배열이었씁니다. 이것을 '1차원 배열'이라고도 하며, 그 이상으로도 선언하고 사용이 가능합니다.

 

int a[2][3] = { {1, 2, 3}, {4, 5, 6} };

int i, k;

 

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

for (k = 0; k < 3; k++)

printf("%d\n", a[i][k]);

 

실행 결과

 

1

2

3

4

5

6

 

 위 예의 첫번째 줄처럼 대괄호를 하나 더 써서 선언했고, 1차원 배열에서 초기화할때의 값을 콤마 ','로 구분하여 중괄호 {}로 묶어 주었습니다. 그리고 각각 배열에 저장된 값을 출력하고 있습니다.

 

 위 예의 배열 'a'는 이런 모양이라고 생각해볼 수 있습니다.

 

[ 1 ][ 2 ][ 3 ]

[ 4 ][ 5 ][ 6 ]

 

 사실 메모리상에는 이것들이 한줄로 들어가 있지만 개념을 잡기 위해 입체적으로 나타내본 것입니다. 어쨋든, 이런 형태를 '2차원 배열' 이라고 하고, 예에서 '1, 2, 3' 과 '4, 5, 6' 과 같이 가로방향의 한줄을 '행', '1, 4', '2, 5', '3, 6' 과 같이 세로로 한줄을 '열' 이라고 합니다. 그래서 2차원 배열은 이런식으로 선언이 됩니다.

 

자료형 변수명[행의 갯수][열의 갯수];

 

 이런식으로 3차원의 배열일 경우 큐브 같은 6면체 모양 생각하시면 되는데, 배열을 이런식으로 우리가 머리속에 어떤 사물이나 그림으로 연상하여 이해하게 되면, 고차원 배열일 수록 상상할 수 있는 모양이 떠오르지 않게 되어 햇깔리기만 합니다.

 

 아래를 봅시다.

 

int a[2][3][4][5][6][7];

 

 int형 배열 a를 6차원으로 선언하였습니다. 이런걸 그리 쓸일은 많이 없습니다만, 배열의 이해를 위해 예를 들어보았습니다. 6차원이기에 이것을 어떤 입체적인 도형으로 머리속에서 연상하기가 사실상 불가능 합니다. 그래서 그런 행이니 열이니 하는건 그냥 '그렇구나' 하고 알고만 계시고, 다음과 같이 선언의 맨 뒤에서부터 단순하게 생각하면 됩니다.

 

7개를 넣을 수 있는 공간이 있는데   →  1차원

그게 6개 있고                                →  2차원

또 그게 5개 있고                            → 3차원

...

이 모든게 2개 있다.                        → 6차원

 

 그림이 그려지지 않아도 충분히 알 수 있을겁니다. 원소의 갯수를 한번 계산해봅시다.

 

7 → 1차원

7 * 6 → 2차원

7 * 6 * 5 → 3차원

...

7 * 6 * 5 * 4 * 3 * 2 → 6차원 

 

 

 사실 배열 원소의 갯수 구할 일도 거의 없습니다. 배열의 개념을 잡는데 도움이 되시라고 한번 적어봤습니다.

 

 

 

 4. 프로그램 적용

 

 오늘 알아본 '배열'을 이용해서 '성적관리 프로그램'에 여러명의 성적을 입력받아 출력하도록 수정해 봅시다. 우선 변수 선언부터 다음과 같이 고쳐줍니다.

 

void main()

{

char name[20][20] = {'\0'};   // 이름

char grade = '\0';                 // 등급

int scoreKOR[20] = {0};              // 국어점수

int scoreMAT[20] = {0};              // 수학점수

int scoreENG[20] = {0};              // 영어점수

int scoreSCI[20] = {0};               // 과학점수

char comment[20][200] = {'\0'};        // 평가

 

int index = 0;                         // 입력받을 배열 위치

 

...

 

 

 오늘 알아본 배열을 사용해서, 입력받는 부분에 사용한 변수들을 20개만큼의 배열로 선언을 해 주었습니다. 20개라는건 결국 20명까지만 입력을 받을 수 있다는 이야기입니다. 또한 초기화할때 배열은 {}를 사용해야 하므로 해 주었습니다. 뒤의 int형 변수 index는 현재 입력받아야 하는 배열의 위치를 저장하게 됩니다.

 

 다음으로, 입력 부분을 다음과 같이 고쳐줍니다.

 

...

 

switch (menuChoice)

{

case '1':

{

// 사용자 입력

do

{

printf("이름을 입력하세요 : ");

scanf_s("%s", temp, sizeof(temp));

len = strlen(temp) + 1;

if (len > sizeof(name[index]))

printf("너무 긴 이름을 입력하셨습니다.\n");

else

strcpy_s(name[index], sizeof(name[index]), temp);

} while (len > sizeof(name[index]));

printf("국어점수를 입력하세요 : ");

scanf_s("%d", &scoreKOR[index]);

printf("수학점수를 입력하세요 : ");

scanf_s("%d", &scoreMAT[index]);

printf("영어점수를 입력하세요 : ");

scanf_s("%d", &scoreENG[index]);

printf("과학점수를 입력하세요 : ");

scanf_s("%d", &scoreSCI[index]);

getchar();

printf("평가를 입력하세요 : ");

gets_s(comment[index], sizeof(comment[index]));

index++;

}

 

break;

 

...

 

 

 

 일반 변수였던 것들을 배열로 선언하였기 때문에, 모두 배열로 바꿔주었고, []안에는 index 변수를 넣어 주었습니다. 모든 입력을 받고 마지막에 index를 1 증가시켜 입력을 다음 배열로 받도록 하였습니다.

 

 출력문도 고쳐보겠습니다. 이전까지의 출력문은 여러명의 성적을 출력하기에는 보기 좋지 않으므로 출력 모양도 바꿔보겠습니다.

 

...

 

case '2':

{

int i = 0;

 

// 상단 출력

printf("이름\t\t등급\t국어\t수학\t영어\t과학\t총점\t평균\t평가\n");

printf("----------------------------------------------------------\n);

 

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

{

// 총점 계산

scoreTotal = scoreKOR[i] + scoreMAT[i] + scoreENG[i] + scoreSCI[i];

// 평균 계산

scoreAverage = (float) scoreTotal / 4;

 

// 평균값에 대응하는 등급 구하기

if (scoreAverage >= 90)

grade = 'A';

else if (scoreAverage >= 80)

grade = 'B';

else if (scoreAverage >= 70)

grade = 'C';

else if (scoreAverage >= 60)

grade = 'D';

else

grade = 'F';

 

// 화면 출력

printf("%s\t\t", name[i]);

printf("%c\t", grade);

printf("%d\t", scoreKOR[i]);

printf("%d\t", scoreMAT[i]);

printf("%d\t", scoreENG[i]);

printf("%d\t", scoreSCI[i]);

printf("%d\t%.1f\t", scoreTotal, scoreAverage);

printf("%s\n", comment[i]);

}

 

getchar();

}

break; 

 

...

 

 기본적으로 입력받는 코드와 같이 일반 변수로 선언된 것들을 배열로 바꿔 주었습니다. 맨 위에 printf() 두줄로 출력 내용이 무엇인지를 먼저 출력해주고, for문으로 i가 index보다 작을때까지 반복하면서 출력합니다.사용한 출력문에 '\t' 서식문자는 키보드 'TAB'키를 누른것과 같은 것으로, 줄을 맞추기 위해 사용했습니다. 이제 잘 되는지 확인해봅시다.

 


 실행을 한 후, 5명을 입력하고 출력해 보았습니다. 만약 배열을 쓰지 않았다면 상당히 많은 변수를 따로 선언해줘야 했을 것입니다.

 

 이번부터는 특별히 복잡하지 않으면 전체 소스코드를 올리지 않겠습니다. 위에서 이미 프로그램 소스코드 고치는 부분을 설명했기 때문에 또 전체 소스코드를 올리는 것은 글 길이만 늘어날뿐 중복 내용인 것 같다는 생각입니다. 글을 보고 잘 모르시겠다면 제 유튜브 체널로 오셔서 동영상으로 보시면 어떤 부분을 어떻게 고쳤는지 좀더 자세히 알 수 있을 겁니다.

 

 다음시간에는 C언어 하면 딱 떠오르는 그것, '포인터'에 대해 알아보도록 하겠습니다.

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
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