[C언어]배열, 다차원 배열과 문자열에 대해서 알아봅시다.
Study/C, C+, C++

[C언어]배열, 다차원 배열과 문자열에 대해서 알아봅시다.

728x90
반응형

배열은, 빼놓을 수 없는 필수요소라고 할 수 있습니다.

 

우리가 보통, 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" }; /* 자동으로 세로값은 원소의 갯수가 됨*/

이렇게 말이죠!

이상입니다! 도움이되셨길 바랍니다.

 

728x90
반응형