배열은, 빼놓을 수 없는 필수요소라고 할 수 있습니다.
우리가 보통, 5개의 정수를 입력받고자 한다면 5개의 정수형 변수를 선언해야 합니다.
int a, b, c, d, e; /* 5개의 정수를 입력받기위한 5개의 변수 */
하지만 배열을 이용하게되면, 같은 데이터형의 변수를 메모리에 연속적으로 할당시키고 같은 이름으로 사용할 수 있게 합니다.
int arr[4]; /* arr[0] 부터 arr[3]까지 크기가 4인 배열 선언 */
이렇게 배열을 사용하게 되면, arr[0], arr[1], arr[2]. arr[3] 이렇게 같은 함수의 이름으로, 번호를 지정해서 사용할 수 있습니다.
주의해야할 점은, arr[4] 라면, arr[0]부터 arr[3]까지 크기가 4인 배열을 선언 하게 되는 것 이므로
int arr[4]; /* 여기서 [4]는, 배열의 크기를 의미함 */
arr[0] = 1;
arr[1] = 20;
arr[2] = 11;
arr[3] = 21; /* 크기가 4인 배열 할당 완료 */
arr[4] = 30; /* 여기서 4는 배열의 5번째 값을 의미하므로, 오류발생! */
이렇게 된다는겁니다! 이해하셨나요?
또한, 저번에 알아보았던 정수형 변수와 문자열 처럼, 초기화를 하지 않으면 덤프값(쓰레기값)을 갖게 됩니다.
따라서, 반드시 초기화를 하고 사용하는게 좋습니다.
int arr[4] = {1,2,3,4}; /* 대괄호로 묶어서 순서대로 초기값 할당 가능 */
int nice[3] = {1,2}; /* 크기가 3인데, 2가지밖에 할당안했으면 나머지는 0 으로 자동 초기화 */
여기서 주의해야할 점은, nice[3]={ }; 이런식으로 초기값을 아예 안줘버린다고 해서 0으로 초기화가 되는게 아닙니다.
이럴 경우에는 오류가 발생합니다. 따라서 초기값은 1개 이상을 설정 해야, 나머지가 0으로 초기화 됩니다.
물론 배열도, scanf_s 등을 통하여 값을 직접 입력받을 수 있습니다.
#include <stdio.h>
#define NUMB 5 /*NUMB라는 매크로 상수에 5를 지정*/
int main(void) {
printf("Start point\n");
int arr[NUMB] = { 0 }; /*int형 배열 선언, 초기화*/
int i, sum;
double pg;
printf("[%d]개의 정수 입력 : ", NUMB);
for (i = 0; i < NUMB; i++) {
scanf_s("%d", &arr[i]); /* 배열을 입력받는다*/
}
for (i = 0, sum = 0; i < NUMB; i++) {
sum += arr[i]; /* sum 에 배열의 값들을 모두 더함*/
}
pg = (double)sum / (double)NUMB;
printf("배열의 합 : [%d] 평균 : [%.2f]", sum, pg);
return 0;
}
sum은 정수형 변수이기 때문에 %d를, pg는 실수형이기 때문에 %f를 이용하여 출력합니다.
이런식으로, 배열의 값을 직접 입력받아 합과 평균을 구할 수 있습니다.
그렇다면, 배열에 있는 항목들을 정리해서 보여주는 프로그램은 어떻게 만들까요?
다음 프로그램은, 배열에서 작은 값부터 차례대로 출력해주는 프로그램입니다.
#include<stdio.h>
#define SIZE 10
int main(void){
int arr2[SIZE] = { 1,2,3,5,32,12,34,22,11,9 };
int a, b, index, temp;
for (a = 0; a < SIZE - 1; a++) {
index = a;
for (b = a + 1; b < SIZE; b++) {
if (arr2[index] > arr2[b]) {
index = b;
}
}
temp = arr2[a];
arr2[a] = arr2[index];
arr2[index] = temp;
}
printf("선택 정렬 완료 : ");
for (a = 0; a < SIZE; a++) {
printf("%d ", arr2[a]);
}
printf("\n");
}
역시 배열의 값은 사용자가 입력하게 할 수 있으며, 임의로 넣은 숫자들을 작은 숫자부터 순서대로 출력하게끔 해줍니다.
프로그램을 실행하면
선택 정렬 완료 : 1 2 3 5 9 11 12 22 32 34
이렇게 출력이 되겠죠.
그렇다면, 1차원 배열이 아닌 다차원 배열은 무엇일까요?
말 그대로, 인덱스를 둘 이상 사용하는 배열입니다!
똑같이 연속된 메모리에 할당이 되며, 간단하게 '표'와 같다고 생각하시면 됩니다.
int olleh [4][3]; /* 3개씩 묶어서 4줄인 배열 ( 3x4 의 테이블과 같다고 생각 ) */
이걸 테이블로 표현을 한다면
이런 형태가 되겠죠. 진짜 더 간단히 말한다면, int 변수명[세로][가로]; 라는 겁니다.
그럼, 이러한 2차원 배열은 채워지는 순서가 어떻게 될까요?
int olleh[2][3]; /* 3개씩 2묶음인 2차원 배열 선언 */
olleh[0][0]=1;
olleh[0][1]=2;
olleh[0][2]=3; /* 첫번째줄 0~2 까지 3개를 채웠음 */
olleh[1][0]=4; /* 두번째줄 0~2 까지 3개를 채우기 시작 */
olleh[1][1]=5;
olleh[1][2]=6;
이런식으로 되는거죠.
그리고 이러한 배열을 확인하고 싶다면 for문을 이용해서 출력하면 됩니다.
#include<stdio.h>
int main(void){
int k[2][3] = { {1,2,3},{4,5,6} }; /* 2차원 배열 선언 및 초기화 */
int q, w;
for (q = 0; q < 2; q++) { /* 세로 크기 */
for (w = 0; w < 3; w++) { /* 가로 크기 */
printf("[ %d ] ", k[q][w]);
}
printf("\n");
}
}
배열의 값을 설정하고, 위 프로그램을 실행해보면
[1] [2] [3]
[4] [5] [6]
이렇게 출력이 되면서, 배열의 각 원소들이 잘 들어가 있는것을 확인할 수 있죠.
1차원 배열과 같이, 원소를 1개 이상적고, 나머지를 안적으면 자동으로 0으로 초기화가 됩니다.
또한, 저는 { {1,2,3}, {4,5,6} } 이렇게 묶었지만
{1,2,3,4,5,6} 으로 해도 같은 의미입니다. 즉, 첫번째 줄의 배열이 가득차면 그다음 인덱스로 넘어가서 마저 채우는 형식이죠.
한가지 더 팁을 공유하자면 int k[ ][2] = {1,2,3,4,5,6}; 를 하게 되면, 가로가 2칸이라는걸 알 수 있죠. 따라서 1,2,3,4,5,6 을 가로로 2줄로 세우게 되면서 자동으로 int k[3][2]; 로 할당 됩니다.
하지만 반대로 int k[3][ ]를 하게 되면, 가로 길이가 정해지지 않았으므로 오류가 발생합니다.
그럼 여기까지 정수를 저장하는 배열이였구요, 그렇다면 문자를 저장하는 배열은 어떻게 해야할까요?
문자를 저장하는 배열은, null값(\0)을 같이 저장합니다. 따라서, 배열의 크기를 저장할 문자열의 크기(길이) + 1 로 할당해야 하는데요!
char str[5] = { 'a','b','c','d' }; /* 길이가 4인 문자열을 저장하기 위한 배열*/
for (i = 0; i < 4; i++) {
printf("%c ", str[i]);
}
이렇게 하고 출력을 해본다면, 출력값은 a b c d 가 되겠죠!
배열에는 5를 할당했지만, \0 (null) 값이 자리할 한 칸을 줘야하기 때문입니다.
문자열 역시, 크기를 정하지 않고 생략이 가능합니다.
char str[ ]="hello";
를 하게 되면, 자동으로 5글자+1(null) 를 해서, str[6]과 같게 되는거죠.
또한 빈공간이 생기면, 모두 \0(null) 값이 들어가게됩니다.
그리고, 문자 한개 가 아니라 문자열 전체를 출력하고 싶다면, %s 형식을 사용하거나, printf(str); 을 해서 str의 모든 요소를 출력할 수 있습니다.
char str[5]="nice"; /* 4글자 + null값 할당 완료 */
str = "good"; /* 배열의 원소가 아닌, 배열 전체에 다른 문자 대입 불가능. 오류발생 */
자, 여기서 str[5]="nice"; 를 했습니다. 이게 무슨 의미냐면
str[0] = n
str[1] = i
str[2] = c
str[3] = e
str[4] = \0 (null값)
이라는 듯이 되겠죠! 즉, str[1]="p" 로 했다면, str[1]의 원소가 p 로 바뀌게 하는건 가능하다는 소리입니다.
문자열을 변경하려면, strcpy 함수를 이용하면 됩니다.
다만, 이렇게 하기 전 str 함수를 사용하기 위해서, 소스파일 최상단에 #include <string.h> 헤더를 추가해 주어야 합니다.
char pp[20], ap[20];
strcpy (pp, "home\n"); /* str1 에 'home' 을 복사해서 대입.*/
strcpy (ap, pp);/* str2에 str1의 값을 복사해서 대입, 크기가 넘어가면 오류발생*/
printf("pp = %s",pp);
printf("ap = %s", ap);
실행결과
pp = home
ap = home
이렇게, pp에 home 을 복사하고, ap에 pp를 복사한 것을 확인할 수 있습니다.
널값을 제외한, 문자열의 길이도 구할 수 있습니다.
char qq[] = "maplestory"; /* qq에 크기가 11인 배열(글자수+널) 할당 */
int len = strlen(qq); /* len 이라는 정수형변수에, qq의 길이를 삽입 */
printf("qq의 길이 = %d \n", len);
실행결과
qq의 길이 = 10
이렇게 널값을 제외한 문자의 갯수를 출력할 수 있습니다.
굳이 배열에 안넣고, printf("길이 = %d\n", strlen("im groot");
를 해도, 실행결과는 잘 나옵니다. 글자수(공백포함)가 나오는거죠.
그럼, 문자열이 같은지 다른지 비교도 가능할까요? 당연하죠!
if (strcmp(pp, ap) == 0) { /* 같으면 0, 다르면 1을 리턴*/
printf("두 배열은 같은 문자열입니다!\n");
}
else {
printf("두 배열은 서로 다른 문자열입니다!\n");
}
또한, 배열에 공간이 남는다면, 다른 문자열을 추가로 뒤에 붙일 수 있습니다.
char cat[20] = "my name is";
strcat(cat, " groot"); /* cat에 저장된 문자열 뒤에 이어서 붙임 */
printf("%s\n", cat);
이렇게 strcat 을 사용하여, 공간이 남는 문자형 배열 뒤에 붙일 수 있습니다.
문자 가 아니라, 문자열을 출력할때는, %s를 사용하죠. scanf 에서도 마찬가지 입니다.
하지만, 공백 문자(띄어쓰기, \n, \t 등)를 포함 하여서 읽는건 scanf가 할 수 없는데요.
이럴때는 gets 함수를 이용해야 합니다.
char Location[20];
char msg[40];
printf("장소를 입력하세요 : ");
gets(Location);
sprintf(msg, "%s의 식당은 김치를 제공하나요?", Location); /* sprintf를 통해 msg에 뒤의 메세지를 저장.*/
puts(msg);/*한 줄의 문자열을 출력*/
여기서 puts(msg); 는 msg를 출력하는걸 의미합니다.
문자열을 여러개 저장하려면, 문자열 배열을 선언해야합니다.
정수형 배열처럼, 2차원으로 선언해 주면 됩니다.
char A[3][5]; /* 길이가 4인 문자열을 3개 저장가능한 문자열 배열 선언 */
분명히 A[3][5] 인데, 길이가 왜 4일까요? 바로 null 값이 포함되어야 하기 때문입니다.
char A[3][5]; /* 최대 4글자까지, 3번 저장가능한 배열*/
strcpy(A[0], "good");
strcpy(A[1], "to");
strcpy(A[2], "see");
A[2][0] = 'S'; /* 한 글자 일때는 ' 를 붙임*/
for (i = 0; i < 3; i++) {
printf("문자열 : [%s] 길이 : [%d]\n", A[i], strlen(A[i]));
}
실행결과
문자열 : [good] 길이 : [4]
문자열 : [to] 길이 : [2]
문자열 : [See] 길이 : [3]
이렇게 2차원 배열을 선언하고, 각 배열에 문자열을 입력한 뒤, 특정 위치의 문자를 바꾸는 방법과 출력까지 알아보았습니다.
마찬가지로 세로 크기를 생략할 수 있고, 대괄호로 묶어서 한번에 설정할 수도있습니다.
char B[][10] = { "My","name","is","freezino" }; /* 자동으로 세로값은 원소의 갯수가 됨*/
이렇게 말이죠!
이상입니다! 도움이되셨길 바랍니다.
'Study > C, C+, C++' 카테고리의 다른 글
[C언어]포인터 연산에 대한 개념 정리. (182) | 2019.06.20 |
---|---|
[C언어] 포인터에 대해서 알아봅시다. (141) | 2019.04.21 |
[C언어] 변수와 데이터형 알아보기. (0) | 2019.04.20 |
[C++] 입력받은 숫자 두개를 더해주는 프로그램 코드입니다. (0) | 2018.09.19 |