전체 페이지뷰

2014년 10월 24일 금요일

Selection Sort (선택정렬)



선택정렬(Selection Sort)란
정렬 대상의 레코드중 하나를 선택하여 정렬해나아가는 방식의 정렬 알고리즘이다.
쉽게말해서 무작위로 정렬된 값들중에 최소값을 찾아 맨앞에놓고 그다음 작은것을 찾아서 그뒤에놓는 방식이다.(오름 차순일경우)
아래 예제를 보면 알수있겠지만 시간복잡도는 O(N^2)이 된다.





5, 17,






2014년 10월 23일 목요일

5. C에서 C++로.....

< C에서 C++로 >


  • 힙의 메모리할당과 소멸
  • new와 delete


C++ 리터럴을 쉽게 알아보자.


"Literal" , 리터럴
이라고 불리는 이녀석은 도대체 누구일까.
쉽게 알아보도록 하겠다.

Literal 또는 Literal constant 라고 불리는이 녀석은
특정한 메모리공간에 이름이 없이 임시적으로 저장되어있는 값을 의미한다.

간단하게 예제를 보고 알아보자.

아주 간단하고 직관적으로 이해할수 있는 코드다.
여기서 num 은 무엇인가? 바로 '변수'이다. 이는 당연히 우리가 알고있다.
그러면 10 + 100; 여기서 10과 100은 무엇인가?
바로 이와 같이 사용되는게 리터럴이다. num = 10+ 100;을 하게되면
메모리공간엔 이름이 없이 10과 100이라는 값을 저장하게된다.
그리고 이값을 사용한후 다음줄로 넘어가게되면 메모리공간에서 사라지게된다.

리터럴은 상수(constant)다. 그렇기에 리터럴 상수(Literal constant)라고도 불리는 것이다.
10과 100은 자체적으로 바뀔수도없고 변할수도 없는 그냥 10과 100이 되는것이다.
num = 10+100;
num = 50;
을한다고해서 10+100 이 50으로 바뀌는게 아니라 num이 50으로 바뀌는 것뿐이다.
10과 100은 여전히 그대로인 값이다.

C&C++에서는 그럼 어떤것들은 리터럴 상수로 정의할까.

정수 리터럴 값 : 1, 5, 100, 10023, 39342
실수 리터럴 값 : 1.84, 4.52, 0.524, 044412
문자 리터럴 값: "안", "녕", "A", "B", "C" 
문자열 리터럴 값 : "안녕하세요", "HI", "HELLO"

위에 보인것과 같은 것들을 상수로 정의한다. 





















2014년 10월 21일 화요일

C++ 참조자 소멸에 관하여

반환형이 참조형인 함수에서

참조자의 소멸에 대해 정확히 이해하자.









반환형이 int& 이고 매개변수를 int &ref로 받는 Reference 라는 함수가 정의되어있다.
(ref 값을 1증가 시킨후에 참조자 ref를 반환한다.)

메인 함수 

"참조형 반환 1" 부분을 먼저 보도록하자.

int &n2 = Reference(n1) 에서 n2는 Reference 함수에서 반환된 참조변수를 참조하게된다. 다시말해, n2 는 ref가 참조하고 있는 n1을 참조하는것과 같다.
따라서 n1과 n2의 값은 같기때문에 "참조형 반환 1" 의 결과를 보면 n2++ 를 했을때 n1의 값과 n2의 값이 함께 증가함을 알 수 있다.

다음

"참조형 반환 2" 부분을 보도록하자.
int p2 = Reference(p1) 으로 정의된 부분이다. Reference 함수에서 반환된 참조변수 ref를 int형 변수 p2에 저장하였다. 참조자가 아닌 일반 변수를 선언하여 반환값을 저장하여도 된다는 것을 알 수 있다. 이렇게 된다면 "참조형 반환 1" 과는 다르게 p1과 p2는 각각 별개의 저장공간과 값을 가진 변수가 된다. p2++후 출력결과를 보면 p1 과 p2 각각 다르게 값을 가지는것을 알 수 있다.


결론 :
반환형이 참조형인 함수를 이용했을때, 반환된 값을 어떻게 저장하느냐에 따라 결과가 다른 상황이 발생한다. 그러므로 잘 생각하여 사용하도록 하자.




처음 예제와는 다르게 반환형이 int 형인 함수를 정의하였다. RefEx() 함수를 통해 얻게된 반환값을 각각 int val2, int &val3 에 저장하였다. 그랬더니 &ref 에서 에러가 발생.



에러 문구는 "int에서 int &로 변환 할수 없다"
당연하다 RefEx() 함수를 통해 반환된 값 int형을 가진 ref는
참조자 ref가 아니라
참조자 ref가 가리키는 변수 val1의 값이다.

따라서 int val2 변수에는 저장이 가능하지만
int &val3 에는 저장이 불가능 하다.
왜냐면 int &val3 = 10 이 된단소린데, 상수(number)는 const형태가 아닌이상 참조자로 선언 할 수 없다.











2014년 10월 20일 월요일

C++ 템플릿 사용시 error LNK2019


책에서 배운 그대로 프로그래밍하였는데

왜 에러가날까?

바로 선언과 정의 파일을 나누어 만들었기 때문이다.


간단한 예를 보도록 하자.




<Pos.h> 헤더파일에서 선언을



<Pos.cpp> 파일에서 정의를


<test.cpp> 메인함수에서 실행


 보이는것과 같이 error LNK2019 에러 발생.

위 문제의 해결을위해 클래스 템플릿의 선언과 정의를 구분하지 않고 한곳에서 해보기로 하겠다.
Pos.cpp 파일을 제거후에 헤더파일에 주석(/*  */) 부분 제거후 재 실행.




<Pos.h> 선언과 정의를 한번에한 헤더파일



위에 사용한 메인함수와 같음(변경x)



<실행결과>  문제없이 컴파일이 되었다.


  • 결론
 " C++ (Template)템플릿을 사용하여 구현한 코드는 선언과 정의를 같은 파일에서 해야한다. 왜냐면 컴파일할때 템플릿 소스코드를 만들어내는데 이때 템플릿의 정의가 헤더파일과 Cpp 파일에 나뉘어져있으면 제대로 템플릿 코드가 생성되지 않을 수 있기 때문이다. (런타임시 소스코드를 만들어내는게 아님) "


물론 Cpp파일을 메인Cpp파일이 컴파일시 참조할수 있도록 include 해주면 되긴한다. 하지만 그냥 편하게 헤더파일 하나에다가 정의해서 쓰도록 하자. 귀찮다.









2014년 10월 14일 화요일

4. C에서 C++로.....(3)

< C에서 C++로 >

  • 자료형 bool
  • 참조자

안녕하세요. 벌써 네번째 강의의 시작입니다.
오늘은 C++에 새롭게 추가된 자료형 bool 그리고 참조자(reference)에 대해서 알아보도록 하겠습니다. 조금 이해하기 어려울수 있겠지만 노력하면 안될 것 은 없다고 봅니다. 힘냅시다!

(출처 : C++ for everyone 2nd edition)

bool을 알아보기에앞서 우리는 먼저 true(참)과 false(거짓)에 대해서 확실하게 알고 넘어가야합니다. C에서는 우리는 보통 매크로상수를 이용하여 참을의미하는 숫자는 1거짓을 의미한는 숫자는 0 로 사용을 하였었죠.

#define TRUE  1
#define FALSE   0
이렇게 계속사용하다보니 무의식적으로 우리는 TRUE =1, FALSE=0 으로 생각하게 되는데 TRUE는 반드시 1이어야하는것은 아니고 FALSE 또한 반드시 0이어야하는것도 아니랍니다.
단순히 참과 거짓을 구별하려고 사용한것이기 때문이죠. 앞으로 는 참과 거짓을 숫자의 의미로서 생각하지마시고 말의 의미 그대로 참, 거짓으로 생각하길 바라겠습니다.

bool이란 무엇일까?
C++에서는 C에서와는 달리 bool이라는 자료형을 새롭게 추가하였습니다. 이 자료형은 단 두가지의 값만을 가지게됩니다. 바로 "True" 와 "False" 입니다. 말그대로 참과 거짓을 의미합니다. 
bool은 int, double과 마찬가지로 기본자료형과 같기 때문에 보통 변수를 선언할때 처럼
bool Love = true;
bool Love = false; 
이렇게 선언과 초기화가 가능하답니다.

위에 그림에 보시면 boolean Truth table(부울 진리표)가 있습니다. bool형에대한 AND, OR 연산에 대한 결과표 인데요. (bool도 자료형이기에 연산이 가능합니다.)
AND 연산일때는 거짓이 하나라도 있으면 거짓, 모두 참일때만 참.
OR 연산일때는 참이 하나라도 있으면 참, 모두 거짓일때만 거짓.
이렇게 생각하시면 됩니다. 

가장 아래에 표를 보시면 연산자들과 우선순위에 대한 설명이 나옵니다. 아까 말했듯이 bool도 자료형이기에 기본자료형과 동일한 방식으로 사용을 할 수 있습니다.


자그럼 바로 사용해봅시다.



CheckNum 함수를 보도록 하겠습니다. 반환형은 bool , 매개변수를 int num으로 받습니다. 그리고 받아온 num이 0보다 작으면 false를 크면 true 를 출력하는군요.
이전에 함수를 정의해오던 방식과 같습니다. 중요한점은 반환형이 bool 이기때문에 true 
또는 false가 return 되야 한다는점입니다. 아시겠나요?

메인함수에서 키보드로부터 입력받은 숫자를(isnum) CheckNum 함수를 이용해서 0보다 큰지 작은지 판단후에 true 와 false 를 저장해줍니다.(bool Number에)
그리고 if-else 조건문을 이용해서 양수인지 음수인지 화면에 출력을 해주게 됩니다.
아주 쉬운 부분이라 문제없이 이해되실겁니다~
bool에 대해서는 이정도로 알고 넘어가도록 할게요.


다음은 참조자(Reference)에 대한 부분을 다루어 보겠습니다.
참조자도 C++에서 처음등장하는 개념으로 다소 생소한 부분이니 정확하게 알고 넘어가셔야 합니다.

'참조자' 는 말 그대로 참조를 하는 녀석입니다. 어떤 방식으로 참조를 하는 것일까요?
간단하게 예를 들어 보겠습니다.

제 이름은 김철수 입니다. 친구들은 저에게 "직소" 라는 별명을 지어줬습니다. 그래서 친구들은 저를 부를때 철수야 또는 직소 라고 부른답니다.
이 문장을 보면 김철수 = 직소  이렇게 볼 수 있습니다. 그러므로 철수를 부를 때 "철수야!" 라고 해도되고 "직소!" 이렇게 불러도 철수는 고개를 돌리며 "응?" 이라고 대답하는 것이겠죠. 참조자도 바로 이런 역할을 한답니다.

컴퓨터가 알아들을수 있게끔 이야기를 바꾸자면
변수 A에 100이라는 숫자가 저장되어있다. 참조자를 사용해서 A의 별명을 B로 지어주었다. 그랬더니 B를 호출해도 100이라는 숫자를 얻어올 수 있었다. 정도가 됩니다.
참조자의 개념에 대해서 어느정도 이해가 되시나요?

이제그럼 참조자를 사용하는법을 알아보겠습니다.




int A = 100; (변수 A에 100이라는 숫자가 저장되어있다.)
int &B = A;  (참조자를 사용해서 A의 별명을 B로 지어주었다.)
cout << B << endl; (그랬더니 B를 호출해도 100이라는 숫자를 얻을수 있었다.)

이렇게 사용하는게 참조자입니다. 해당 대상에 별명을 지어 주는것이죠.
위 코드를 보면서 머리를 갸우뚱하게 만들만한 부분이 있습니다. 바로 "&B" 이 부분인데요. 우리는 이전에 & 연산자를 변수의 주소값을 반환하는 연산자로 사용해왔습니다. 하지만 여기서 & 연산자는 전혀 다른 의미로 사용이 되어지는 것을 알 수가 있습니다. 이 둘을 어떻게 구분 하는지는 다음을 따릅니다.

* 이미 선언된 변수의 앞에 &연산자를 사용하면 주소 값의 반환
* 새로 선언되는 변수의 이름 앞에 &연산자를 사용하면 참조자의 선언

int *ptr = &A; (A의 주소값을 반환해서 포인터 ptr에 저장)
int &B = A;  (변수 A에 대한 참조자 B를 선언)
그러므로 B는 A의 참조자가 되는 것입니다. 

(*포인터의 개념과 교차시켜 스스로 골머리를 앓게 하시면 안됩니다. 포인터에 개념은 잠시 넣어두세요)

참조자는 변수로 보아야하는가? 참조자가 하는 기능, 연산, 결과 등은 변수와 동일합니다. 하지만 C++에서는 참조자와 변수를 구분해서 이야기 합니다.

참조자의 주소값에 대한 예제를 하나 보도록 하겠습니다.




위 예제를 보면 참조자에도 역시 &연산자를 사용하면 참조자의 주소값을 가져올 수 있다는걸 알수가 있습니다. 그리고 변수 a의 참조자 ref1, ref2, ref3 들의 주소값 역시 변수 a의 주소값과 동일 하다는 것을 알 수 있죠. 왜냐면, ref1, ref2, ref3은 변수 a의 별명이니까요. 

주소값이 모두같다는건 변수와 참조자들이 같은 공간을 가지고 있다는 소리가 됩니다. 그저 a를 부르게되는 별명만 늘어나는 것 입니다. 또 참조자는 선언할 수 있는 갯수에 제한이 없습니다.(별명이 여러개라고 문제가 안되듯이..) 위와 같이 여러개의 참조자를 선언 해도 문제가 없습니다. 하지만 엄청많이 참조자를 선언하면 본인도 사용하는데 까먹어서 정신이 없을거에요ㅋㅋ

참조자를 선언할때는 중요한 점이 있습니다. 참조자는 앞서 누누히 말했듯이 '변수에 별명을 지어주는것이다' 라고 했습니다. 만약 변수가 아니면? 참조자는 선언이 불가능 하겠지요.

int &ref = 100;
int &ref = NULL;
이 참조자의 선언은 유효할까요? 유효하지 않습니다. 왜냐면 변수를 참조하는게 아니라 상수(number), NULL을 참조했기때문입니다.

int &ref;
여기서 &ref의 선언은 유효할까요? 이것도 역시 유효하지 않습니다. 왜냐면 참조자는 반드시 참조할 대상이 함께 존재해야만 의미가 있습니다.

int &ref = *ptr;
int &ref = arr[0];
이렇게 선언된 참조자는 유효할까요? 이 둘은 유효하답니다. 포인터도 역시 변수며 배열요소도 변수로 간주되어 선언이 가능하답니다. 이점 꼭 알아두시기 바래요.

참조자를 이용한 Call by Reference
C언어에서 우리는 두 수를입력받아 그값을 서로 바꾸어 주는 Swap() 함수를 만들면서 포인터의 활용에대해 이해를 하였습니다. 기억나시죠?
그때의 기억을 잠시 되짚어보면, Call by ValueCall by Reference 이 두가지가 떠오를겁니다. C++ 에서는 참조자를 이용한 Call by reference의 함수호출을 지원합니다. 포인터를 이용해서 만들었던 swap 함수를 이제는 참조자를 이용해서 만들수 있단 말이죠.
다음예제를 보면서 알아보도록 하겠습니다.



Swap1() 는 Call by value 에 의한 두 숫자의 값을 바꾸는것.
Swap2() 는 Call by reference에 의한 두 숫자의 값을 바꾸는것. (포인터사용)
Swap3() 는 Call by reference에 의한 두 숫자의 값을 바꾸는것. (참조자 사용)
이렇게 정의가 되어있습니다. 

swap1() 함수를 사용했을때는 값을 매개변수로 전달했기 때문에 함수 외부에 선언된 변수에 접근이 불가능 하므로 값이 바뀌지 않는 결과가 나타나게됩니다. 하지만 swap2() 함수를 사용했을때는 포인터를 사용하여 주소값을 매개변수로 전달했기 때문에 함수 외부에 선언된 변수에 접근이 가능하여 값이 바뀌는 결과가 나타납니다.
swap3() 함수는 매개변수를 참조자로 선언하였습니다. 참조의 대상이 될 변수를 인자로 전달하게되면 되겠군요! 그렇게 val1과 val2를 전달한뒤 참조자를 통해서 함수내부에서 값을 교환하였더니 서로 바뀐숫자값이 출력이 되었습니다. 도대체 어떻게 이렇게 될까요? 바로참조자를 이용하면 함수 내부에서도 외부에 선언된 변수에 접근이 가능하기 때문입니다. 

(참조자를 쓰면 포인터는 사용안해도 되겠네요? 라고 혹시 생각하는 분이 있겠지만.. 그건 아닙니다. 앞으로 코딩을 하는데 상황에 알맞게 참조자와 포인터 둘다 빈번히 사용하는게 알맞습니다.)

매개변수 부분에 int &a, int &b 로 선언만 되어있고 변수값 참조를 하지않는데 어떻게 swap3() 함수가 에러없이 정의가 가능한지 궁금한 분들이 있으실겁니다. 정확하게 참조자를 이해하고 공부하신분 입니다. 하지만 매개변수는 함수가 호출되었을때 전달되는 인자로 초기화가 되는것이기 때문에 아무 문제가 없습니다. 다시말해서 swap3()함수는 매개변수에 인자가 전달되지 않으면 함수가 실행이안되고 인자가 전달되면 그 순간 선언과 초기화가 이루어져서 함수가 실행된다는 의미랍니다. 

(참조자 팁 <- 여기서 반환형의 참조형(&)인 함수에 대해 알아두시기 바랍니다. 따로 해당 글에서는 따로 정리를 안하도록 하겠습니다.)

const를 이용한 참조자의 선언.
C언어에서 배웠던 const(상수) 한정자에 대한 개념을 간단히 집고 넘어가겠습니다.

*상수는 한번 선언후 초기화를 하면 절대 변하지 않으며 변할 수도 없다.

여기서 const는 참조자는 상수(number)를 참조 할 수 있게 해주는 역할을 합니다. 어떻게 그것이 가능할까요? 다음 예제를 통해 알아보도록 하겠습니다.




const 한정자를통해 int &a = 10으로 초기화 시켰습니다. 이때 저장되는 숫자 10은 바로 "리터럴" 입니다. (리터럴이 생각이 안나면 => 리터럴)
그러면 cont int &a = 10; 다음줄로 넘어가게되면 '10'이라는 리터럴값은 메모리공간속에서 사라지게 됩니다. 그러면 참조자 a는 아무것도 참조할것이 없게되므로 에러가 발생하게되는것이 정상입니다. 그러나 위의 코드는 아무런 에러를 보여주지 않고있습니다. '10'이라는 값이 메모리상에 계속 남아있기 때문에 참조자 a가 참조를 잘하고 있다는 소리겠지요?
여기에 특수한 로직이 하나숨어져있습니다. const 한정자를 이용해서 리터럴을 참조할 때는 메모리에 '임시변수'를 하나 만들어 그곳에 '10'을 저장하여 참조자가 문제없이 참조할 수 있도록 해준답니다. 
또 참조자 a는 const로 선언되어있으므로 절대 값이 바뀔수 없습니다.

이렇게 리터럴을 참조하는 방식을 가지고 더욱 직관적인 함수를 만들어낼 수 있습니다.
아래 예제를 보도록하겠습니다.



addnum1()과 addnum2() 두 함수를 사용할때 차이점 보이시나요?
addnum2() 함수처럼 매개변수 인자를 리터럴로 받아오게 되면 addnum1() 함수를
사용할때 처럼 굳이 val1과 val2를 선언해서 인자전달을 하는 번거로움이 줄어들게
된답니다.

이렇게 자료형 bool과 참조자에대해서 알아보는 시간이 모두 끝났습니다.
다들 쉽게쉽게 이해 되셨길바라면서 강의를 마치겠습니다. 다음강에서 뵙겠습니다.
(궁금한점은 댓글 달아주시면 답변드리겠습니다.)








2014년 10월 7일 화요일

3. C에서 C++로.....(2)

<C에서 C++로>

  • Namespace(이름공간)과 사용법
  • std와 cout,endl,cin
  • using

강의 세번째시간입니다. 내용중에 잘못되거나 부족한 부분이 있으면 지적 부탁드리겠습니다. 그럼 오늘도 즐겁게 공부해 보도록합시다.

Namespace(이름공간)이란 무엇일까요. 전혀 감이 잡히지 않는것이 당연합니다.
간단한 예를 들어 설명하도록 할게요.

철수는 덕구라는 강아지를 키우고있습니다. 덕구를 데리고 공원을 산책하는 도중에 영희와 희동이를 만나게되었습니다. 영희와 희동이도 강아지를 데리고 공원에 산책을 나왔던것이었네요. 철수가 영희와 희동이에게 너네 강아지 이름이 뭐냐고 물었습니다. 영희, 희동이 둘다 '덕구' 라고 대답했습니다. '덕구'라는 같은 이름을 가진 강아지가 셋이되어버렸군요.

위와같은 상황에서 우리는 세마리의 덕구를 어떻게 구분할까요? 대부분 이렇게 구분을할겁니다.
    *철수네 덕구
    *영희네 덕구
    *희동이네 덕구
다들 공감하시나요? 철수네~, 영희네~, 희동이네~ 이게 namespace입니다. 이미 여러분들은 namespace를 현실에서 사용하고 계셨던겁니다.

실제로 프로그램도 대형화가 되면서 함수, 변수등의 이름들이 충돌되는 경우가 많아지게 되었습니다. 위에 예처럼말이죠. 만약 충돌되는 함수와 변수들의 이름을 모두 바꾸어야한다면 여간 성가시고 정신없는 문제가 아닐수 없습니다. Namespace는 이런 문제에 대해 탁월한 해결책을 제시해주고 있습니다.

Namespace 사용법을 알아보도록 하겠습니다.




보이는 예제와 같이 Duckoo()이라는 동일한 이름과 매개변수를 가진 함수를 선언하게 되면 어떻게 될까요?

이렇게 멋진 에러가 하나 등장하게 될겁니다. 당연히 컴퓨터 입장에서는 어떤 함수를 사용해야될지 어리둥절 하겠지요.
그럼 저기~ 위에서 배운대로 철수네, 영희네, 희동이네 처럼 Namespace를 만들어주어서 구분을 하게 해주면 되겠지요?

위에 예제에 다음과같이 코드를 추가하여 보도록 하겠습니다.



Duckoo()라는 함수 두개에 namespace {  } 를 씌워주었습니다.  정말 간단한 사용방법이지요? 저렇게 cheolsoo, younghee namespace를 선언해주면, 앞으로 Duckoo()는 철수네 Duckoo(), 영희네 Duckoo()로 구분이 가능해 지는것입니다. 구분이된 함수는 가져다 사용할때 "누구의" Duckoo()인지 반드시 명시를 해줘야합니다. 
main() 함수를 보면 다음과 같이 사용을 하고있습니다.

cheolsoo::Duckoo(10,5);
( 철수라는 네임스페이스에 정의된 Duckoo()라는 함수를 사용할 것이다!)

younghee::Duckoo(10,10);
( 영희라는 네임스페이스에 정의된 Duckoo()라는 함수를 사용할 것이다!)
앞부분에는 namespace를 뒤에는 함수또는 변수이름을 마지막으로 사이에 구분자 :: 를 넣어 사용해줍니다. 
namespace :: 함수, 변수등의 이름;
어때요 사용방법은 상당히쉽죠?
이제 네임스페이스가 무엇인지 확실히 개념이 잡혀가고 있습니다.

다음 예제처럼 함수의 선언과 정의를 따로따로 나누어해도 됩니다.


namespace :: 함수, 변수등의 이름; 선언방법이 함수를 호출하는데만 사용하는것이 아니라 함수를 정의할때도 위의 예제처럼 활용할 수 있습니다. 이런 방법도 있구나 하고 잘 익혀두시길 바랍니다. 컴파일 결과는 이전 과 동일합니다.

다음예제를 통해 namespace가 가지는 특성을 알아보겠습니다.




위 소스코드를 보시면 cheolsoo라는 이름의 namespace가 중복되게 사용되고 있음을 확인 하실 수 있을겁니다. 하지만 컴파일은 아주 잘되는군요.
namespace는 함수와는 다르게 이름의 중복을 허락합니다. 다시말해 위의 예제처럼 namespace를 둘 이상으로 나누어서 선언을 해도 이 둘은 동일공간이된다는 말이죠.
따라서,

namespace cheolsoo
{
   int Duckoo();
   void marry();
}                     //이렇게 코드를 쓰나

namespace cheolsoo
{
  int Duckoo();
}

namespace cheolsoo
{
  void marry();
}                      // 이렇게 코드를 쓰나
모두 똑같다는 말이됩니다. 이점 염두해두세요~

namespace younghee{} 를 보시면 그안에 namespace second, third가 정의되어있는 것을 볼수있습니다. namespace안에 이름이 다른 네임스페이스를 선언을해도 된다는걸 알 수있습니다.
이렇게 정의된 namespace안에 함수나 변수를 호출할때는 namespace의 포함관계에 순서에따라 이전에 호출하던 문장을 사용해주면됩니다. 이렇게말이죠.

younghee::third::marry();
younghee::secon::Duckoo();

네임스페이스::네임스페이스::함수또는변수이름;
어때요 참 쉽죠?
이렇게 알아두셨으면 위 예제는 이해하는데 문제가 없을거라 생각합니다.

예제를 쭉~ 풀어오면서 이상한 부분을 발견하지 않으셨나요??
아마 다들 궁금해하셨던 부분이있을거에요 . 우리가 지금까지 계속 사용해왔던 입출력에 관한 함수! 바로 std::cout, std::endl, std::cin 이 녀석들도 뭔가 수상하다!
네임스페이스를 알게되므로서 우리는 이 녀석들의 정체를 조금 알 수 있습니다.

namespace std라는 곳에 정의된 cout
namespace std라는 곳에 정의된 endl
namespace std라는 곳에 정의된 cin 
그렇다면 std라는 namespace는 어디에 있을까?
바로 <iostream>이라고 맨첫줄에 선언한 헤더파일에 정의되어 있답니다.

어떻게 구현된 함수인지 내용은 정확히 모르지만 이제는 조금 알게되었습니다. 기쁘지않습니까?
조금만 더 배우면 이 녀석들을 완전히 파헤칠수 있는 날이 머지않았습니다. 조금만더 힘내요~

사람은 항상 귀찮은걸 싫어합니다. 저도 역시 귀찮은게 너무싫어요. 매번 namespace를 이용하여 함수와 변수를 정의하면 항상 (예를들어) std::, cheolsoo::, younghee::second.. 이렇게 사용해야 되는걸까요? 답은 No 입니다.
다음예제를 보면 앞으로 손가락이 좀더 편하실겁니다.



맨 첫줄 using namespace std; 보이시나요?
무슨 의미인가 하면 'namespace std안에 정의된 모든 것을 사용할때 namespace 명시를 안해도됩니다' 이런뜻입니다. 그럼 이말이 사실인지 알아보도록하죠.

main() 함수를 보니 std::cin, std::cout, std::endl 로 사용했던것이 cin, cout, endl로 간소화가 되었습니다. using 키워드 너무너무 고맙네요.

이렇게 길고긴 namespace의 단원이 끝났네요. 다들 이해가 잘되셨으면 좋겠습니다.
오늘강의도 고생많으셨고, 다음가의때 뵙도록 하겠습니다. 화이팅!





















2014년 10월 6일 월요일

2. C에서 C++로.....(1)

<C에서 C++로>

  • 함수 복습
  • 함수 오버로딩


안녕하세요. 2번째 강의시간입니다.
저도 C, C++언어를 배워가는입장에서 작게나마 지식을 공유하고자 이렇게 포스팅을 하게됬습니다. 잘못된 부분이있으면 지적해주시어 서로서로 윈윈하자구요^^

먼저 함수라는 녀석을 슬슬건드리기전에 이 녀석이 도대체 누구인지
왜 사용을하게되었는지 알아봐야겠죠?
C언어에서 이미 공부를 마치셨겠지만 다시한번 복습겸 알아보도록 합시다.

함수를 사용하는 이유를 여러 책들에서 살펴보면 이렇게들 표현이 되어있습니다.
1. 모듈화에 의한 프로그램의 질 향상 가능
2. 유지 보수 확장의 용이성
3. 문제해결의 용이성
등등... 와 정말 말이너무 어렵네요. 절대 틀린말은 아니죠. 하지만 초보자는 이해하기가 너무어렵네요. 우리는 아주 쉽게쉽게 이해하고 넘어가도록 합시다.

이 함수라는 녀석은 반복적인 작업을 피하고 효율적인 코딩이 가능하게 만들어 주는 역할을 수행합니다. 우리가 앞서배운 입출력함수 cout, cin을 사용할때
cout << "hello world"; 이렇게 사용했었죠?
허나 cout라는 함수가 없었다면 어떻게 출력을 어떻게 했을까요? 출력을 할때마다 이 기능들을 매번 코딩을 해주어야 한답니다. 너무 귀찮아지고 코드라인수가 엄청나게 많아지겠지요. 그렇기에 함수가 이용이 되는것입니다.

따라서 함수라는 녀석을 알기쉽게 정리한다면
어떤 특정한 작업을 독립적으로 수행하는 프로그램! 이라고 보면 되겠습니다.

함수는 그럼 어떻게 만들고 사용할까요?
위 그림은 함수의 기본적인 형태입니다.
1. 반환자료형(리턴타입)
2. 함수이름
3. 인수목록(매개변수)
4. 함수몸체 및 리턴값
으로 구성이 되어있으며 위의 형식에 맞게 만들어서 사용하시면 된답니다.


다음예제를 가지고 함수의 호출과정은 어떻게 되는지 한번 살펴보도록 하겠습니다.

메인함수위에 addNum() 이라는 두 숫자를 입력받아 그 합을 리턴하는 함수를 정의하였고 이를 메인함수에서 사용하는 코드입니다.
함수가 호출되는 시점은 간단합니다. 그 함수가 사용될때 실행이되고 함수 사용이 끝나면 값을 리턴하고 메인함수가 다시 시작이 되는겁니다.

그림으로 쉽게알아보자면 


 
 위의 절차를 따라 함수는 작업을 수행하게됩니다.  어때요 참쉽죠?
함수의 사용에 대하여 보다 자세히 알기위해서는 C++언어의 메모리 구조에 대하여 자세히 알아야할 필요성이 있습니다.

프로그램을 실행시키게 되면(프로그램 시작시) 우리의 컴퓨터에 설치된 운영체제(OS)들은 RAM이란 곳에 메모리 공간을 할당해준답니다. 할당되는 메모리 공간은 크게 세가지
1. 데이터영역
2. 스택영역
3. 힙영역
으로 나눌수가 있습니다. 바로 이곳에 우리가 선언한 함수들, 변수들 등등 모든게 적절한 위치에 할당된답니다.
(C언어 메모리구조에 관하여 http://dsnight.tistory.com/50 블로그에 포스팅 되어있는 자료를 가져왔습니다. 문제가될시 삭제후 재업로드 하겠습니다.)


자 이 그림을 보면 이렇게 분류를 또 할수가 있겠군요.
데이터 영역에는 전역변수와 Static 변수들을
힙영역에는 프로그래머가 할당한 것들을
스택영역에는 지역변수와 매개변수들을
할당한다고 알 수 있게됩니다.
(좀더 자세한 설명은 http://dsnight.tistory.com/50 블로그에 잘정리가 되어있습니다. 반드시 이해하시고 넘어오세요)

드디어 함수 복습시간이 끝났습니다.
이제 함수 오버로딩에 대하여 알아보도록 하겠습니다.

먼저 예제를 한번 보도록 할게요.

반환형이 int형이고 각각 3개, 2개의 int형 매개변수를 가지는 함수가 정의되어 있습니다. 매개변수의 합을 Num 변수에 저장하여 리턴을 해주는 기능을 하고있군요.

예제를 쭉 한번 훑어보니 무언가 이상한 부분이 보이지않나요?
앞서 설명한 함수가 addNum() 이라는 같은 이름을 가지고있었습니다.
하지만 컴파일했을때는?? 문제가 없습니다.
기존에 C에서는 동일한 이름을 가진 함수가 정의되는것을 허용하지 않았습니다. 하지만 C++에서는 허용을 합니다. 단, 조건이 지켜졌을 경우에 허락이 된답니다.
그 조건은"함수 호출시 전달되는 매개변수의 타입과 갯수에 따라 호출하고자하는 함수를 구분할 수 있다!"
입니다.

위의 예제를 보면 addNum() 함수는 다음과 같이 두가지로 정의 되어있습니다.
addNum(매개변수 2개), addNum(매개변수 3개).
컴퓨터에게 addNum(5,2) 호출을 부탁하면, 컴퓨터는 이름이 addNum()이고 2개의 매개변수를 가지고있는 함수를 찾아서 함수를 사용할 것입니다.
반대로 addNum(5,2,5) 호출을 부탁하면 컴퓨터는 이름이 addNum()이고 3개의 매개변수를 가지고있는 함수를 찾아서 사용하겠지요. 이것이 함수 오버로딩의 전부랍니다.
앞으로 오버로딩을 할때 항상 매개변수의 타입과 갯수에 대하여 신경을 쓰도록 합시다.

C++ 함수에는 매개변수에 디폴트값(Default Value)을 정의해 줄 수 있습니다.
쉽게 말해서 매개변수가 기본값을 가지도록 해주는 것이죠. 사용법은 아주 간단합니다.


addNum(int x=0, int y=0, int z=0)이 보이시나요?
매개변수에 그냥 값을 초기화 시켜주는 방법입니다. 아까 말했듯이 참 간단하죠?
이렇게 디폴트값을 선언해 주었으면 main()함수에서 addNum()함수를 사용할때 매개변수값을 전달하지 않아도 문제가 없습니다. 결과값을 한번 보도록할게요.



sum4 = addNum(); 부분을 보시면 매개변수를 하나도 전달해주지 않았습니다. 따라서 디폴값인 x=0, y=0, z=0으로 초기화가 되어 sum4의 결과값이 '0' 으로 올바르게 출력이 되었습니다.

sum1을 보면,
sum1 = addNum(3);으로 매개변수를 '3' 하나만 전달하여서 함수를 호출하였습니다. 이때는 매개변수는 왼쪽 부터 값을 채워나갑니다. 쉽게말해 x=3, y=0, z=0 이렇게 초기화가 된다는 뜻이지요.
따라서 sum2 = addNum(3,4);은 매개변수를 3,4 두개를 전달하였으므로 x=3, y=4, z=0 으로 sum3 = addNum(3,4,5);은 매개변수를 3,4,5 세개를 전달하였으므로 x=3, y=4, z=5로 초기화가 됩니다.

위 예제를 통해 이런 결론을 낼수가 있겠군요.
"전달되는 매개변수는 왼쪽부터 초기화되며 부족한 부분은 디폴트값으로 초기화된다"

그런데 꼭 디폴트값을 전부다 설정해주지는 않아도됩니다. 부분적으로 디폴트값을 설정해줘도 문제는 없습니다. 하지만 여기에도 조건이 따르는데

다음에서 보이는것과 같이

int addNum(int x, int y=0, int z=0) { ....}
int addNum(int x, int y, int z=0) { ....} 
이런식으로 설정해주어도 문제는없습니다. 

하지만
int addNum(int x=0, int y, int z=0) {....}
int addNum(int x=0, int y=0, int z) {....}
int addNum(int x, int y=0, int z) {....}
이렇게 우측 매개변수의 디폴트값설정을 안해주게 되면 문제가 발생하게됩니다. 다시말해서, 디폴트값이 설정된 매개변수를 기준으로 오른편 매개변수들중 단하나라도 매개변수가 설정이 되어있지 않다면 잘못된 함수 정의가 되는것입니다. 꼭 유념하셔야합니다!

이렇게 두번째 강의가 끝났습니다.
저도 배워가는 입장에서 기술한 허접한 강의였지만
작게나마 서로에게 도움이 되었길 바랍니다. 고생하셨습니다. 다음강에서 뵙겠습니다.













2014년 10월 4일 토요일

1. Hello C++

 블로그에 방문하신 모든분들께 감사의 말씀을 드립니다. 아주 수준높은 프로그래머는 아니지만 제가 가진 지식을 공유해서 서로 WINWIN 하고자 이렇게 블로그 포스팅을 하게 되었습니다. 프로그래밍언어를 공부하고자하는 분들에게 작은 도움이 되었으면 좋겠습니다.
(C언어를 반드시 미리 공부하고 오셔야합니다. 그래야 충분히 이해하실수 있습니다. 또한 C언어를 알고있다는 전제하에 강의를 진행하려합니다.)

Hello C++

다들 반갑습니다. C++ 1강입니다. ( 포스팅한게 갑자기 지워져서 날짜가 밀림)
이번 1강에서는

  • Hello World! 와 변수사용
  • 입출력함수
  • 헤더파일 선언
  • 조건문 반복문
에 대하여 가볍게 알아보는 시간을 가지도록 할게요.
무슨 언어든 프로그래밍을 배우려고 책을 펴면 항상 가장 첫 부분은 "Hello World"라는 문자를 출력하는것이 장식을합니다. 그리고 시키는대로 따라서 코딩을합니다. 이게 왜 "Hello World"라고 출력이되는지도 모른채 말이죠. 처음배울때는 코드가 동작하는 방식, 이유 등은 모르는게 당연합니다. 반복적으로 학습해서 몸에익히고 더 많이 배우게되면 하나씩 그 원리들을 알게되어 가게되니까 너무 조바심내지마시고 차근차근 공부해 나아가도록 합시다.

먼저 Hello World 출력 예제를 살펴보도록 할게요.




첫 줄부터 소스를 분석해보도록 할겠습니다. 헤더파일 선언 문을 한번 보도록할게요.
#include <iostream> 가 눈에 보입니다. C언어에서 표준입출력 함수의 사용을위해 <stido.h>를 포함했지만 C++에서는 <iostream> 형태를가진 헤더파일이 추가되어야합니다. 그런데 iostream 헤더에는 확장자(.h)가 안보이네요? 확장자를 써주지 않았을뿐이지 C언어 때와 동일하게 확장자는 .h 가 맞습니다. C++에서는 프로그래머가 정의한 헤더파일이 아니라 표준 헤더파일을 선언할때는 확장자를 생략한답니다.

이제 헤더선언은 이해가되었고 밑으로 내려가 보도록할게요.
main() 메소드가 나왔네요. 사용법이 C언어와 다를바가없습니다.. main()메소드 안쪽을 들여다 보도록하죠.
int a= 100, int b= 50, double c= 3.14  변수를 선언하고 초기화 하는방법은 C언어와 역시나 일치합니다. 늘 봐왔던 부분이라 정말 익숙하네요. 쪼금만 더 내려가보도록합시다.
당혹스럽군요.  cout?? endl?? 이라는 새로운 녀석이 등장했습니다. 하지만 자세히 보면 이 두 가지 함수를 이용해서 출력을 하는구나라고 생각할 수 있습니다. C언어에서 사용하던 printf는 이제 보이지가 않네요. 그럼 한번 cout, endl에 대해서 알아보도록 하겠습니다.

std::cout<<는 출력을 해주는 함수 입니다.
사용하는 방식은
std::cout<< 출력할 대상;
출력할 대상에는 정수, 실수, 문자열, 변수등 뭐든지 사용할 수 있습니다.  C언어에서 쓰던 printf 함수와는 달리 %d, %s같은 문자를 이용해서 출력포맷을 지정하지 않아도 데이터 타입에 상관없이 잘 출력이 된다는겁니다. 사용하기 참 편한 함수죠? 앞으로 C++ 에서는 꼭 이 함수를 사용해주도록 합시다.

<<std::endl;는 개행을 도와주는 함수입니다.
사용하는 방식은
<< 연산자 다음에 std::endl;
앞으로 배울 강의에 저 뒤편에서 알게 되겠지만 <<도 연산자랍니다. 일단은 << 다음에 std::endl; 을 사용하여 개행을 할 수 있다는 것만 알아 두도록 합시다.

C언어와는 다른 방식에 출력함수 사용을보고 혼란이 오셨을거라 생각합니다. 하지만 로마에 온이상 로마법을 따라야겠지요. 반복적으로 사용하여서 몸에 익히도록해요~
이렇게 출력함수를 가지고 데이터의 연속출력을 해보도록 합시다.

std::cout<< "안녕" << "하세" << "yo" <<std::endl; 
연속 출력방법은 아주 간단하네요. << 연산자를 이용하여
<< 출력대상 << 출력대상 << 출력대상; 방식으로 사용하면 된다는걸 알 수 있습니다.

출력함수가 있으면? 당연히 입력함수도 있습니다. C언어에서 열심히 사용했던 scanf를 대신해줄 무언가가 또 있겠지요?

키보드로부터 3가지의 숫자를 입력받아 출력하는 예제를 통해 알아보도록 하겠습니다.



std::cin 이 등장했습니다. 사용법을 먼저 알아보도록 할게요.

std::cin >> 입력받값을 저장할 변수;
이렇게 사용합니다. cout나 endl과는 다르게 (<<) 꺽쇠방향이 반대로 (>>) 되어있군요.
입력받아서 >> 이쪽방향에 변수에 넣어준다. 이렇게 편하게 생각하시면 됩니다. 자세한건 나중에 다 알게될거에요^^

위에 예제는 int형 변수 first, second, third 3개를 선언해주고 각각 std::cin 함수를 이용해서 값을 받아주고 출력을 해줍니다. 이제 쉽게 이해가 되시죠?

다음은 배열을 이용한 문자열출력을 알아보도록 하겠습니다.



char 배열이름[길이]; 이렇게 선언을 해주는건 역시나 C언어에서 사용하던 방식과 같습니다. subject와 professor 이름을가진 char형 배열에 각각 입력을 받아 출력을 해주고 있네요. 앞서 배웠던 예제와 별차이가 없습니다!! 쉽게 쉽게 따라오실거라 믿어요.

이제 여러분은 c++에서 어느정도 데이터를 입력받고 출력하는데 능숙해지셨습니다.
마지막으로 반복문과 조건문을 이용한 예제를 한번 살펴보도록 하겠습니다.


0보다 큰수를 5개 입력받아 배열에 저장후 그 중에 가장 큰 큰값을 찾아내는 예제입니다.



1. arr[5] 배열에 5개의 숫자를 차례로 입력을 받습니다.
while{ } 문과 if( )문이 등장했네요. C언어때와 사용 방법이 동일함을 알 수 있습니다. arr[count] 에서 count 값을 0 에서부터 1씩 증가시켜 각각 값을 입력받은후에 if( ) 문에서 count 값이 5가 되었을때 break 를 이용하여 while문을 빠져나오게 됩니다.

2. int형 변수 max를 0으로 초기화합니다. max와 배열 arr[0]을 비교해서 큰값을 max에 넣어주고 그 다음 max와 arr[1]을 비교해서 큰값을 max에 넣어주는 방식을 arr[4] 까지 반복하게되면 max에 최대값이 저장되게 됩니다. 간단하죠?

오늘은 이렇게 C++에 대하여 간단하게 알아보았습니다. C언어를 이미 알고 오신분들이기에 그닥 어려운 부분은 없을거라 생각합니다. C++의 정점을 향해 앞으로 힘냅시다.
다음 강의때 뵙겠습니다.