본문 바로가기

Programming/C - 학습노트

20180126. 1차원 배열. rand() 함수.

1. 1차원 배열


생각외로 많은 사람들이 배열의 개념에 대해 잘 이해를 못하고 있는것 같아서 놀랐습니다. 배열은 (현재 시점에서는) 정말로 단순한 구조를 지닌 변수에 불과하므로. 겁 먹지 않아도 됩니다.



1-A. 배열의 정의



배열을 단순하게 정의하자면 다음과 같습니다.


같은 형태의 여러 개의 변수들을 묶어둔 변수들의 묶음.


우리가 익히 알고 있는 변수를 그림으로 표시하면 다음과 같이 표시할 수 있습니다.


<int a= 27;>


배열은 이 변수들을 한데 묶어둔 묶음, 즉


이렇다는 이야기입니다..


그런데, 이렇게 해 놓으면 각 층에 있는 놈을 부르기가 참 애매합니다. 그래서 번호를 붙이게 됩니다.


이제 방 번호를 붙였으니 각 방에 있는 놈들을 가리키기가 쉽게 되었습니다. 단지 주의할점은 이 배열이란 놈은 방 번호를 1번이 아니라 0번부터 매긴다는 점.  이점에 대해서는 아래 배열의 선언 방법과 함께 알아보도록 하겠습니다.



1-B. 배열의 선언(생성)


     int       a      [     5     ]      =     {   2   ,   27   ,   137   ,   14   ,   99   };

자료형식 배열명   배열갯수       =     { 0번방, 1번방,  2번방 ,  3번방,  4번방);


배열은 자료형 배열명 뒤에 대괄호를 붙인 후 배열의 크기를 설정합니다. 그 이후 중괄호 안에 0번방부터 순서대로 들어갈 자료를 넣어주면 됩니다. 물론 생략해도 되고, 그 경우는 해당 자료형은 0으로 초기화되게 됩니다.


헷갈리는점은 바로 이것. 위에서도 언급한것처럼 배열의 방 번호는 1번이 아니라 0번부터 시작합니다. 즉


int a[5] = {2,27,137,14,99} // int형 배열 a는 방의 총 수가 다섯개라는 의미이다. 방은 0번부터 시작하므로 a[0] a[1] a[2] a[3] a[4]로 총 다섯개가 생성되며 a[5]는 존재하지 않는다.


진짜 별거 아닌것처럼 보이는데, 이게 의외로 헷갈리게 만드는 경우가 있습니다. 아래 코드를 보면,


1
2
3
4
5
6
7
8
 
 
int arr[5= {11,212,203,414,2555};
 
for(int a=1 ; a <6; a++) { // a:1 ~a:5까지 다섯바퀴 돕니다
 
    printf("배열 arr의 [a]번째 데이터는 %d 입니다",a , arr[a]);
    }
cs


위의 For문의 경우 a가 1이고 , a가 6과 같거나 6보다 커지는순간까지 총 5회(1,2,3,4,5) 루프하게 됩니다.

그리고 해당 루프마다 위에 arr배열의 내용을 출력하게되는데, a의 수에 따라 각각 arr[1],arr[2],arr[3],arr[4]arr[5]를 출력하게 됩니다.


물론 결과는 다음과 같습니다.


배열 arr의 [1]번째 데이터는 212 입니다

배열 arr의 [2]번째 데이터는 203 입니다

배열 arr의 [3]번째 데이터는 414 입니다

배열 arr의 [4]번째 데이터는 2555 입니다

배열 arr의 [5]번째 데이터는 845689234679134235 입니다


이 글을 쭉 읽어온 사람은 눈치챘겠지만, arr배열은 요소가 5개. 즉 0번부터 4번까지 밖에 없습니다. 따라서 arr[5]는 존재하지 않으며, 컴파일러에 따라 에러를 띄우거나, 위처럼 쓰레기 값을 던져주는 경우도 있습니다. (존재하지도 않는 5번에 값이 있다는건 나중에 포인터와 배열의 관계를 설명할떄 잠시 따로 설명할게요) 따라서 위 결과는 배열의 첫번째 항목이 누락되고, 의미 없는 쓰레기값이 하나 추가된 형태로 출력되었습니다.


추가로, 배열을 선언할 떄, 배열의 갯수를 입력하지 않으면, 컴퓨터에서 자동으로 크기를 정해주게 됩니다. 즉

int numbers[] = {1,2,3,4,5,6,7,8,9} ;

이경우 배열의 크기는 컴퓨터가 자동으로 9로 맞춰 줍니다.


1-C. 배열의 사용


배열을 사용하는 방법은 다음과 같습니다.


  • 배열에 값을 넣기 (배열은 위에 그림에 설명된 int a[5]를 그대로 쓴다고 가정합니다)
a[1] = 27;    // a배열 2번째 방( 0번 방 1번 방 2번 방 3번 방 4번 방)에 20을 넣었음.


  • 배열값을 사용하기
int number =  a[4];  // a배열 5번째 방(0번방 1번방 2번방 3번방 4번방) 값을 number변수에 넣었음.
 위 배열대로라면 number에는 99가 들어갔을 것.



1-D. 대체 배열을 왜 쓰는건데?


만약에 이런 상황이 있다고 가정합시다.


기획팀원 5명의 생년월일을 변수에 담아서 관리하세요


변수로 만들면 이런 모양이 될 겁니다.

int C_S_Kim = 19940217;

int J_C_Jo = 19850417;

int M_H_Choi = 19920708;

int M_S_Jeong = 19890427;

int J_G_Kang = 19880107;

 

배열로 만들면 이런 모양이겠네요

int Birthdays[5] = { 19940217,19850417,19920708,19890427,19880107};


훨씬 더 간편하게 관리가 가능합니다.


무슨 차이인지 모르겠다는 분은, 배열을 쓰지 말고 다음 코드를 짜 보기 바랍니다.

2017년 12월 기준 부산광역시의 시민 총 347만 653명의 생년월일을 관리할 변수를 만드세요

우선 배열로 해보겠습니다.

int Citizen_Birthdays[3470653] ={0, }  // 0, 은 모든 요소를 0으로 초기화한다는 명령입니다.


변수로....해보실 분 계신가요? 

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

생략하겠습니다.


물론 이런 의문이 들 수도 있습니다.


변수는 사람 이름이라도 변수명으로 써둘 수 있지 배열은 그것도 안되잖아? 어떻게 찾으라고? 번호가 누군지 다 외워????


우린 1차원 배열만을 배우고 있습니다. 2차원 배열로 가게되면 데이터 수가 2개가 되면서 더 편리하게 사용할 수 있습니다 (머리는 더 아파지겠지만요...)




2. rand()함수


rand함수는 랜덤한 값을 반환하는 함수입니다. 아주 심플한 기능입니다. 사용법은 다음과 같습니다.


int number = rand() % 10    / 0~9까지의 랜덤한 수를 도출하여 number 변수에 저장합니다

int number2 =rand() %100 +1   / 1~100까지의 랜덤한 수를 도출하여 number2변수에 저장합니다.


뭐가 이리 복잡한데?


뭔가 희한한 외계어가 많이 붙는건 rand()함수의 성질에서 기인합니다. 

rand함수는 말그대로 랜덤한 숫자를 아무렇게나 내뱉습니다.즉


35897619864864648

-5616544138

6354646

645371384138483634

-7845124615846846384138331

-4841643587143534


뭐 이딴식으로 막 내뱉는다는 소리입니다. 따라서 이걸 우리가 써먹기 좋은 형태로 가공하기위해 연산을 거칩니다. 즉. 


int number = rand() % 10    / 0~9까지의 랜덤한 수를 도출하여 number 변수에 저장합니다


뒤의 %10은 우리가 익히 아는 "10으로 나눠서 나머지를 구한다"고 하는 그 연산자입니다. 즉 컴퓨터가 어떤 수를 내뱉는다고 해도 그걸 10으로 나누면 나올 수 있는 나머지는 0 1 2 3 4 5 6 7 8 9밖엔 없습니다. 결과적으로 저 연산을 거치고 나면 0~9사이의 랜덤한 수가 생성되는 셈이 됩니다.


2-1. 사전작업


앞서 필요한 함수가 있으면, 해당 함수가 구현되어있는 헤더 파일을 추가해야 한다고 말씀드렸습니다. rand()함수 역시 해당 함수가 구현되어 있는 헤더 파일을 추가해야 합니다.


#include <iostream>  //rand() 함수가 구현되어 있습니다

#include <time.h>     // 사전작업용 시간을 참조하기위한 헤더입니다


또한 main함수에 다음과 같은 구문을 추가해줍니다.


srand((unsigned int)time(0));


이는 랜덤으로 튀어 나오는 숫자를 제한하겠다는 의미입니다. 약간의 설명을 하자면


unsigned int : 부호(sign)가 없는(un-) INT형. 즉 정수 중 부호달린 정수인 음수를 제외한 양수만 뱉어낼것

time : 그 수를 현재 시각과 결부해서 연산할 것.


다시 말해 이 코드는 랜덤수 중에 양수만 골라서 뱉되, 현재 CPU내의 시간과 연산을 통해 중복없이 랜덤숫자를 출력하도록 하는 구문입니다.