[ C++ 스터디 ]

자료출처 : 열혈강의 C++ 프로그래밍
자료저자 : 윤성우

 

★ printf와 scanf를 대신하는 입 출력 방식 ★

" Hello world " 메시지를 출력하는 프로그램을 기억하는가 ? C 언어를 처음 공부하는데
있어서 이보다 좋은 예는 없으리라 생각한다. 여러분도 그렇게 생각하지 않는가 ? 프로그
램이 아주 간단 하면서도 함수라는 기본 개념을 우리에게 심어 주었다. 그러나 그 프로그
램도 처음 접하는 사람에게는 그리 쉬운 내용이 아니다. 아무 생각 없이 한번 돌려보니 뭔가
가 출력되는 것은 알겠는데 , 어떠한 과정을 거쳐서 출력되는지를 처음부터 정확히 이해할
수는 없었다. 결국은 눈에 익히고 외워 버리게 된다.

우리는 C++이라는 언어를 공부하고 있다. 물론 시작은 " Hello world " 메시지를 출력하는
데서 부터 시작할 것이다. 그러나 그 무게감은 C 언어를 공부할 때 접했던 " Hello world "
프로그램과는 다소 차이가 있다. 아무튼 여러분은 눈에 익히고 외우는 수밖에 없을 것이다. 
걱정할 것 없다. 이는 아주 긍정적인 현상이다.

 

< 1 " Hello world " 의 출력 : 과거 스타일 ! >

다음 예제를 실행해 보자 기본적인 실행 방식은 C 프로그램을 실행하는 것과 동일하다.
단 ! 파일의 이름을 지정할 때 확장자는 반드시 .c 가 아니라 .cpp 로 지정해 줘야 한다
그래야 C++ 문법 규칙이 적용되기 때문이다.

/*
HelloWorld1 . cpp
Old Style Hello World !!
*/

# include < iostream.h >

int main ( void )
{

cout << " Hello world !! " << endl ;
cout << " Hello " << " World !! " << endl ;
cout << 1 << ' a ' << " String " << endl ;
return 0 ;

}

▶ 실행 결과
Hello World !!
Hello World !!
1aString


위 예제와 샐행 결과를 비교해 보면 출력에 관한 몇 가지 특징을 파악할 수 있다.
이해하려 들지 말자. 다만 어떻게 출력이 되는지 관찰만 하면 된다. 위 코드를 통해서
네 가지 사항에 대해서 관찰이 가능하다.

( 첫째 )
입 . 출력에 관련된 일을 하기 위해서 iostream.h 라는 이름의 헤더 파일을
포함해야 한다. C 언어에서는 헤더 파일 stdio.h를 포함했지만, C++에서는 헤더
파일 iostream.h를 포함해야 한다. 이는 # include < iostream.h > 라인을 통해서
확인할 수 있다. # include < iostream.h > 이 라인을 주석처리 하고 컴파일해 보
자 그리고 오류가 발생하는 위치도 확인해 보기 바란다.


( 둘째 )
출력을 하기 위해서는 다음과 같은 형태를 취해야 한다.

cout << 출력대상

" 출력 대상 " 의 위치에는 무엇이든 올 수 있다. 정수 및 실수를 비롯해서 문자열 또
한 올 수 있다. C 언어의 printf 함수는 출력하고자 하는 대상의 출력 포맷을 정의해
줘야만 했다. 그러나 C++의 이러한 출력 방식은 우리가 원하는 형태로 출력을 해 준
다.

아무리 생각해 봐도 여러 가지로 편리하다. 그러나 C 언어에 익숙한 친구들이라면 바
로 의문이 생길 것이다. cout 은 도대체 무엇이고 << 연산자는 또 어떠한 의미를 지
니고 있는 것인지 그리고 출력할 대상의 자료형이 각양각색임에도 불구하고 어떻게
적절히 출력이 이루어지는지 말이다.

이 모든 것을 완벽히 이해하기 위해서는 어느 정도 진도를 나가야만 한다. 그 때까지
는 궁금해도 참고 기다리자.


( 셋째 )
출력 대상을 이어서 표시할 수 있다. 즉 다음과 같이 출력할 대상이 둘 이상이라면
<< 연산자를 이용해서 연속적인 출력을 요구할 수 있다.

cout << 출력대상1 << 출력대상2 << 출력대상 3

cout << 1 << ' a ' << " String " << endl ; 라인을 보자 다음과 같은 형태로 출력
을 요구하고 있다.

cout << 1 << ' a ' << " String " << endl ;

이 문장은 가장 먼저 정수 1을 출력하고, 그 다음으로 문자 'a' 를 출력하고, 그 다음으
로 문자열 " String " 을 출력하고, 마지막으로 endl 을 출력하라는 의미이다. 그런데
여기서 endl 을 출력하라는 것은 어떤 의미일까 ?


( 넷째 )
endl 을 출력하라는 의미는 다음 줄로 넘어가라는 의미를 지닌다. ( 개행 문자를 출력
하라는 뜻 ) 이것을 가장 쉽게 이해할 수 있는 방법은 위의 프로그램에서 endl 을 지웠
을 경우에 보여지는 출력 결과를 확인하는 것이다.

위 예제를 통해서 기본적으로 모니터에 데이터를 출력하는 방식은 알게 되었다. 그러나
의문점은 많이 남아 있다. 우리는 아직 cout 와 << 연산자, 그리고 endl 의 정체를 모
른다. 다만 사용할 줄만 알고 있을 뿐이다. 진도를 나가면서 이들의 정체를 서서히 알게
될 것이다.

참고 => endl 을 출력할 경우 개행 문자를 출력하게 되고, 추가로 출력 버퍼를 비우는
효과도 얻게 된다. 따라서 C 언어에서처럼 버퍼를 비우는 작업을 추가로 할 필요가 없
다.


< 2. " Hello world " 의 출력 : 현재 스타일 ! >

위에서 보여준 예제는 과거에 사용된 프로그래밍 스타일이다. 새롭게 정의된 C++ 표준
에서는 다른 형태의 프로그래밍 방식을 요구하고 있다. 다음 예제는 위의 예제와 같은
일을 하는 프로그램이다. 다만 새로운 표준에 부합하도록 프로그램을 변경했을 뿐이다.

/*

HelloWorld2 . cpp
Standard Style Hello world !!

*/

# include < iostream >

int main ( void )
{

std : : cout << " Hello World !! " << std : : endl ;
std : : cout << " Hello " << " World !! " << std : : endl ;
std : : cout << 1 << 'a' << " String " << std : : endl ;

return 0 ;

}

▶ 실행 환경
Hello World !!
Hello World !!
1aString


실행 결과를 보면 HelloWorld1 . cpp와 같은 기능을 하는 프로그램이라는 것을 알 수 있다.
그렇다면 어떤 부분에서 차이를 보이는가 ? 차이가 나는 것은 두 가지이다.

첫째 | # include < iostream > 라인을 보면 헤더 파일의 이름이 iostream.h 가 아니라
iostream 이다.

포함하고자 하는 헤더 파일의 이름에 확장자가 없다는 것에 대해 상당히 생소한 느낌을 받
을 것이다. 이는 구 버전의 헤더 파일과 새로운 버전의 헤더 파일을 구분하기 위한 것이다.

새로운 표준이 정의되는 과정에서 기존의 C++ 표준에 존재하던 헤더 파일에 일부 변경
이 가해졌다. 그래서 기존의 헤더 파일과 새로운 헤더 파일을 구분 짓기 위해서 이러한 방
법이 제안된 것이다. 물론 우리는 앞으로 새로운 표준 헤더 파일을 사용할 것이다.

둘째 | HelloWorld1 . cpp와 비교해서 cout << " Hello world !! " << endl ; 이 라인을
보면 cout을 대신해서 std : : cout을 사용하고 있고, endl을 대신해서 std : : endl 을 사
용하고 있음을 볼 수 있다. cout이 무엇인지 , 그리고 endl 이 무엇인지도 모르는 판국에
그 앞에 " std : : " 까지 붙여버리니 답답하기 그지 없다 ( 붙여주지 않으면 컴파일 에러가
발생한다. ) 잠시만 기다리자. 이번 장 마지막에서 이에 대한 궁금증을 풀어 볼 것이다.


< 3. 데이터의 입력 : 과거 스타일 ! >

이번에는 키보드로부터 데이터를 입력받는 방식에 대해서 이야기해 볼 차례이다. 다음 예
제는 사용자로부터 두 개의 숫자를 입력받아서 덧샘 결과를 출력하는 프로그램이다.

/*

SimpleAdder1 . cpp

*/

# include < iostream.h >

int main ( void )
{

int val1 , val2 ;  // double val1 , val2 ;

cout << " 첫 번째 숫자 입력 : " ;
cin >> val1 ;

cout << " 두 번째 숫자 입력 : " ;
cin >> val2 ;

int result = val1 + val2 ;   // double result = val1 + val2 ;
cout << " 덧셈 결과 : " << result << endl ;

return 0 ;

}

▶ 실행 결과 1
첫 번째 숫자 입력 : 3
두 번째 숫자 입력 : 4
덧셈 결과 : 7


위 예제를 통해서 알 수 있는 두 가지 특징은 다음과 같다.

첫째 | 키보드로부터 데이터를 입력받기 위해서는 다음과 같은 형식을 취하면 된다.

cin >> 입력 변수

" 입력 변수 " 의 위치에는 키보드로부터 입력받은 데이터를 저장할 변수의 이름이 오게
된다. 위 예제의 cin >> val1 ; 이 라인에는 다음과 같은 문장이 등장한다.

cin >> val1 ;

이는 키보드로부터 정수를 하나 입력받아서 미리 선언되어 있던 변수 val1에 대입하라는 의
미이다. 그렇다면 만약에 실수형 덧셈을 하고자 한다면 위의 예제를 어떻게 바꿔야 하겠는가 ?
int val1 , val2 ;  // double val1 , val2 ; 이 쪽 라인에 그리고
int result = val1 + val2 ;   // double result = val1 + val2 ; 이 쪽 라인에 선언되어 있는
변수의 자료형을 실수형 ( float 혹은 double형 )으로 변경 만 해 주면 된다.

다음은 int 형 변수의 선언을 double형으로 변경 한 다음 실행했을 때의 결과이다. 실수를
입력하고 있는 부분을 유심히 보자.

실행 결과2
첫 번째 숫자 입력 : 4.5
두 번째 숫자 입력 : 3.2
덧셈 결과 : 7.7

즉 cout을 이용한 출력이 자료형에 맞는 적절한 출력을 보장했던 것처럼 , cin을 이용한
데이터의 입력은 자료형에 맞는 적절한 입력을 보장해 준다는 것을 알 수 있다.

둘째 | C 언어와 다르게 변수의 선언이 어디서든 등할 수 있다 . C 언어로 프로그램을
작성하는 경우에는 함수를 정의함에 있어서 지역 변수의 선언이 항상 제일 먼저 등장
해야만 했다. 그러나 C++은 원하는 위치 어디서나 변수를 선언하는 것이 가능하다.
그래서 위의 예제 int result = val1 + val2 ;   // double result = val1 + val2 ;
이 쪽 라인에 등장하는 변수 result의 선언은 적합한 선언이 된다.

간단한 예제를 하나 더 소개하겠다. 다음 예제는 두 개의 정수를 키보드로부터 입력받아
서 그 사이에 존재하는 정수들의 합을 계산하는 프로그램이다. 예를 들어서 3과 7을
입력받으면 그 사이에 존재하는 정수들 ( 4 , 5 , 6 )의 합을 계산해서 출력해 준다.


/*

BetweenAdder . cpp

*/

# include < iostream.h >

int main ( void )
{

int val1 , val2 ;
int result = 0 ;

cout << " 두 개의 숫자 입력 : " ;
cin >> val1 >> val2 ;

if ( val1 < val2 )
{

for ( int i = val1+1 ; i< val2 ; i++ )
result += i ;

}

else
{

for ( int i = val2+1 ; i<val1 ; i++ )
result += i ;

}

cout << " 두 수 사이에 존재하는 정수의 합 : " << result << endl ;
return 0 ;

}

▶ 실행 결과
두 개의 숫자 입력 : 3  7
두 수 사이에 존재하는 정수의 합 : 15

위의 예제를 통해서도 다음 두 가지 사실을 더 알 수 있다.

첫째 | 연산자를 이용해서 연속적인 데이터의 입력을 요구할 수 있다.


cin >> 입력 변수1 >> 입력 변수2


cin >> val1 >> val2 ; 이 쪽 라인을 보자 다음과 같은 형태로 데이터의 입력을 요구하
고 있다.

cin >> val1 >> val2 ;

이는 첫 번째로 입력받은 데이터를 변수 val1에 입력하고 , 두 번째로 입력받은 데이터
를 변수 val2에 입력하라는 의미이다. 이때 첫 번째 데이터와 두 번째 데이터의 경계는
( 데이터 간의 경계는 ) 공백 ( 탭 , 스페이스바 , 엔터키의 입력 )에 의해 나눠진다. 마치
C 언어에서 제공하는 scanf 함수 처럼 말이다.


둘째 | for문의 초기화 문장 내에서도 변수 선언이 가능하다.
for ( int i = val1+1 ; i< val2 ; i++ ) 이 라인과 result += i ; 이 라인을 보자 for문의
초기화 문장이 오는 곳에 변수의 선언이 함께 등장하고 있다.

즉 다음과 같은 선언은

int i
for ( i=0 ; i<n ; i++ ) { }

다음과 같이 한 줄로 선언이 가능하다.

for ( int i=0 ; i<n ; i++ ) { }

마지막으로 배열에 문자열을 입력 및 출력하는 예제를 소개하겠다. 앞의 예제들과 다를
것은 없다 . 다만 입 . 출력하는 데이터의 종류가 다를 뿐이다.

/*

StringIO . cpp

*/

# include < iostream.h >

int main ( void )
{

char name[ 100 ] ;
char language[ 200 ] ;

cout << " 이름은 무엇입니까 ? " ;
cin >> name ;

cout << " 좋아하는 프로그래밍 언어는 어떻게 되나요 ? " ;
cin >> language ;

cout << " 이름 : " << name << endl ;
cout << " 언어 : " << language << endl ;

return 0 ;

}

▶ 실행 결과

이름은 무엇입니까 ? 기동찬
좋아하는 프로그래밍 언어는 어떻게 되나요 ? C++
이름 : 기동찬
언어 : C++


< 4 데이터의 입력 : 현재 스타일 ! >

앞에서 데이터의 입력에 관련된 여러 가지 예제를 소개하였다. 그런데 문제는 과거의
표준을 따르고 있다는 것이다. 그렇다면 현재의 표준을 따르도록 하려면 프로그램을
어떻게 변경해야 하겠는가 ? 예제 HelloWorld2 . cpp를 참고하면 어렵지 않게 예제들을
변경할 수 있다. 여기서는 예제 SimpleAdder1 . cpp를 현재의 표준에 맞게 변경해
보기로 하자.

/*

simpleAdder2 . cpp

*/

# include < iostream >

int main ( void )
{

int val1 , val2 ;

std : : cout << " 첫 번째 숫자 입력 : " ;
std : : cin >> val1 ;

std : : cout << " 두 번째 숫자 입력 : " ;
std : : cin >> val2 ;

int result = val1 + val2 ;
std : : cout << " 덧샘 결과 : " << result << std : : endl ;

return 0 ;

}

▶ 실행 결과

첫 번째 숫자 입력 : 3
두 번째 숫자 입력 : 4
덧샘 결과 : 7


예제를 현재의 표준에 맞게 변경하는데 있어서 신경 쓸 부분은 헤더 파일을 포함
하는 5번째 줄과 여러 줄에 걸쳐서 여러 번 등장하는 cout , cin , endl을 대신해서
std : : cout , std : : cin , std : : endl 을 사용하는 것이다.

이제 기본적인 입력 및 출력 방식을 이해하게 되었다. 보다 구체적인 이해는 앞으로
내용이 전개 되면서 완성될 것이다. 지금까지 소개한 내용 이외의 궁금한 사항은 시간을 두
고 해결해 가기로하자.


★ 함수 오버로딩 ( Function Overloading ) ★


< 1 함수 오버로딩의 이해 >

확장자가 .c 로 끝나는 C 언어로 작성된 프로그램에서는 다음과 같은 함수의 정의가 허용
되지 않았다.

int function ( void )
{

return 10 ;

}

int function ( int a , int b )
{

return a + b ;

}

int main ( void )
{

function ( ) ;
return 0 ;

}


위의 예제에서 문제가 되는 부분은 어디인가 ? 같은 이름으로 정의되어 있는 함수 부분
이다. 함수의 이름이 같기 때문에 컴파일 타임에 오류를 발생시킨다. 그렇다면 다음 코드
를 보고 여러분께 다시 질문을 던지겠다.

int function ( void )
{

return 10 ;

}

int function ( int a , int b )
{

return a + b ;

}

int main ( void )
{

function ( ) ;
function ( 12 , 13 ) ;
return 0 ;

}

이 코드를 작성한 사람의 마음을 깊이 헤아려 보자 그리고 다시 한번 보자
function ( ) ; 이 라인을 통해서 호출하고 있는 function 함수는 어디에 선언된 함수이겠
는가 ? 과연 어떤 함수가 호출되기를 바라고 저라한 문장을 선언한 것이겠는가 ? 그렇다 !
int function ( void ) 이 쪽 라인에 정의되어 있는 함수를 호출하고자 하였을 것이다. (
전달되는 인자와 정의되어 있는 매개 변수를 참조해서 보면 알 수 있다 . )

그렇다면 12번째 줄을 통해서 호출하고자 하는 function 함수는 무엇이겠는가 ? 아마도
5번째 줄 에 정의된 함수를 호출하고자 하였을 것이다.

그렇다면 다음과 같은 궁금증을 가져볼 수도 있겠다. " 아니 ! 어떠한 함수를 호출하고자 하
는지는 나도 구분하겠는데 왜 ? C 컴파일러는 에러를 발생시키는 것일까 ? "

여러분은 위의 예제를 보면서 function ( ) ; 이 라인에 존해하는 함수의 호출이
int function ( void ) 이 라인에 정의되어 있는 함수를 호출해 달라는 요구이고 ,
function ( 12 , 13 ) ; 이 라인에 존해하는 함수의 호출은 int function ( int a , int b )
이 라인에 정의되어 있는 함수를 호출해 달라는 요구임을 쉽게 알 수 있다.


그림 1-1 : 함수 이름과 매개 변수 정보의 참조를 통한 호출

여러분은 어떻게 구분할 수 있었는가? 호출하고자 하는 함수를 찾을 때 이름뿐 아니라
매개 변수의 정보까지도 동시에 참조했기 때문에 가능한 것이다. 즉 여러분은 호출하고자
하는 함수를 다음 두 가지 정보를 가지고 찾아낸 것이다.


함수의 이름 + 매개 변수의 정보


반면에 C 컴파일러는 호출하고자 하는 함수를 찾을 때 오로지 함수의 이름 정보만을 가지
고 찾기 때문에 매개 변수의 형태가 달라도 동일한 이름의 함수 정의는 허용하지 않는 것
이다.

그렇다면 C++ 컴파일러는 호출하고자 하는 함수를 어떻게 찾을까? 여러분과 마찬가지로
함수의 이름뿐 아니라 매개 변수의 정보까지도 참조를 한다. 따라서 C++은 이름이 같고
매개 변수의 타입 혹은 개수가 다른 함수들의 정의를 허용한다. 그리고 이를 가리켜 함수
오버로딩 ( function overloading )이라 한다.



< 2 함수 오버로딩의 조건 >

C++은 함수의 이름이 같아도 매개 변수의 타입 및 개수가 다르면 문제되지 않으며 , 이를
가리켜 " 함수가 오버로딩되었다 " 라고 표현한다고 하였다. 다음은 대표적인 함수 오버로
딩의 예이다.

int function ( int n ) { }
int function ( char c ) { }


위의 두 함수는 오버로딩되었다. 함수의 이름이 같지만 매개 변수의 자료형이 다르기
때문이다.

int function ( int v ) { }
int function ( int v1 , int v2 ) { }


위의 두 함수도 오버로딩되었다. 함수의 이름과 매개 변수의 자료형은 같지만 자료형의
개수가 다르기 때문이다.

즉 함수 오버로딩의 기본 조건은 다음과 같다.

" 함수의 이름은 같지만 매개 변수의 타입이나 개수가 달라야 한다 "

그 이외에도 함수가 오버로딩되기 위한 조건이 하나 더 있는데 이에 대해서는 다음 기회에
언급하도록 하겠다.

다음 예제는 오버로딩된 함수가 적절히 호출되고 있음을 보여주는 예제이다.

/*

FunctionOverloading . cpp

*/

# include < iostream >

void function ( void )
{

std : : cout << " function ( void ) call " << std : : endl ;

}

void function ( char c )
{

std : : cout << " function ( char c ) call " << std : : endl ;

}

void function ( int a , int b )
{

std : : cout << " function ( int a , int b) call " << std : : endl ;

}

int main ( void )
{

function ( ) ;
function ( 'a' ) ;
function ( 12 , 13 ) ;

return 0 ;

}

▶ 실행 결과

function ( void ) call
function ( char c ) call
function ( int a , int b ) call


function ( ) ; 이 라인을 보면 인자를 받지 않는 function이라는 이름의 함수를 호출하고
있다 따라서 void function ( void ) 이 라인에 정의 되어 있는 함수를 호출하게 된다.

function ( 'a' ) ; 이 라인에서는 function이라는 이름의 함수를 호출하면서 char형 데이터
하나를 인자로 전달하고 있다. 따라서 void function ( char c )  이 라인에 정의되어 있는
함수를 호출하게 된다.


< 3 오해하기 쉬운 함수 오버로딩 >

함수 오버로딩을 처음 접하게 되면 두 개의 함수를 눈으로만 보고 잘못 판단하는 경우가 종
종있다. 예를 하나 들어 보겠다. 다음의 함수들은 오버로딩 조건을 충족하는가 , 아니면
충족 하지못하고 컴파일 시 오류를 발생시키겠는가? 눈 여겨서 볼 부분은 함수의 리턴
타입이다.

# include < iostream >

void function ( void )
{

std : : cout << " function ( void ) call " << std : : endl ;

}

int function ( void )
{

std : : cout << " function ( char c ) call " << std : : endl ;

}

int main ( void )
{

function ( ) ;

return 0 ;

}


위에 정의되어 있는 두 개의 function 함수는 이름은 같지만 , 리턴 타입이 다르다. 그러나
리턴 타입만 가지고는 함수가 오버로딩되었다고 말할 수 없다. 위 예제의 function ( ) ;
이 라인을 보자 이름이 function 이면서 인자를 받지 않는 함수를 호출하고 있다. 문제는 이
조건을 만족시키는 함수가 void function ( void ) 이 라인에도 int function ( void ) 이 라
인에도 정의되어 있다는 것이다. 결국 컴파일러는 " 난 네가 뭘 원하는지 몰라 ( Ambiguous )
" 라는 메시지를 출력하게 된다. 결론이다 ! 리턴 타입만 달라서는 함수가 오버로딩되지 않
는다.

 


★ 디폴트 ( Default ) 매개 변수 ★


< 1 디폴트 매개 변수의 의미 >

함수를 다음과 같은 형태로 정의하는 것이 가능하다.

int function ( int a=0 )
{

return a+1 ;

}


여기서 매개 변수를 선언하는 부분을 보면 a는 0으로 설정되어 있다. 이것이 바로 디폴트
매개 변수이다.


int function ( int a=0 )
{

return a+1 ;

}
디폴트 매개 변수는 ( int a=0 ) 이 부분이다.

위에서 무엇을 가리켜 디폴트 매개 변수라고 하는지를 보여 준다. 현재 매개 변수 a는 0이
라는 디폴트 매개 변수 값이 설정되어 있다. 그렇다면 이것이 지니는 의미는 무엇일까? 의
외로 간단하다. " 만약에 function이라는 이름의 함수를 호출하면서 인자를 전달하지 않으
면 0이 들어온 것으로 간주를 하겠다 " 는 뜻이다 말 그대로 디폴트 ( 기본적으로 설정해
놓은 ) 매개 변수다. 다음 예제를 보자.

/*

DefaultParameter1 . cpp

*/

# include < iostream >

int function ( int a=0 )
{

return a+1 ;

}

int main ( void )
{

std : : cout << function ( 11 ) << std : : endl ;
std : : cout << function ( ) << std : : endl ;

return 0 ;

}

▶ 실행 결과
12
1


int function ( int a=0 ) 이 라인에는 function이라는 이름의 함수가 정의되어 있다. 전달
인자로 int형 데이터를 하나 전달받는다. 그리고 디폴트 매개 변수가 0으로 설정되어 있다.
이것은 이 함수를 호출하면서 아무런 인자도 전달하지 않으면 0이 들어온 것으로 간주하겠
다는 의미이다.

std : : cout << function ( 11 ) << std : : endl ; 이 라인에서는 함수 function을 호출하
면서11을 인자로 전달하고 있다. 따라서 int function ( int a=0 )  이 라인에 정의되어 있
는 함수를 호출하게 된다.

std : : cout << function ( ) << std : : endl ; 이 라인에서는 함수 function을 호출하면서
아무런 인자도 전달하지 않고 있다. 따라서 0을 인자로 전달한다고 가정하게 된다. 즉 다음
두 문장은 같은 의미를 지니고 있다.

" function ( ) " == " function ( 0 ) "


< 2 다양한 형태의 디폴트 매개 변수 설정 >

이번에는 디폴트 매개 변수의 다양한 형태를 예제를 통해서 살펴보기로 하자. 다음에 소개
하는 것은 직육면체의 넓이를 구하는 프로그램이다.

/*

DefaultParameter2 . cpp

*/

# include < iostream >

int BoxVolume ( int length , int width=1 , int height=1 ) ;

int main ( )
{

std : : cout << " [ 3 , 3 , 3 ] : " << BoxVolume ( 3 , 3 , 3 ) << std : : endl ;
std : : cout << " [ 5 , 5 , def ] : " << BoxVolume ( 5 , 5 ) << std : : endl ;
std : : cout << " [ 7 , def , def ] : " << BoxVolume ( 7 ) << std : : endl ;

return 0 ;

}

int BoxVolume ( int length , int width , int height )
{

return length * width * height ;

}

▶ 실행 결과
[ 3 , 3 , 3 ] : 27
[ 5 , 5 , def ] : 25
[ 7 , def , def ] : 7


함수 BoxVolume이 int BoxVolume ( int length , int width , int height ) 이 라인에 정
의되어 있고, int BoxVolume ( int length , int width=1 , int height=1 ) ; 이 라인에 선언
되어 있다. 이러한 형태의 구성은 이미 C 언어를 통해서 학습한 것이다. 여기서 눈 여겨
볼 부분은 함수의 선언이다. 총 세 개의 매개 변수를 인자로 전달받는데 두 번째 , 세 번째
인자에만 디폴트 매개 변수를 설정해 놓았다.

한가지 주의할 것은 이렇게 함수의 선언이 함수의 정의 이전에 존재하는 경우 디폴트
매개 변수는 선언 부분에 놓여져야 한다는 것이다. 보라!
int BoxVolume ( int length , int width , int height ) 이 라인에 있는 함수의 정의에는
디폴트 매개 변수에 대한 내용이 존재하지 않는다. 이미
int BoxVolume ( int length , int width=1 , int height=1 ) ; 이 라인에 선언되었기 때문이다.

std : : cout << " [ 3 , 3 , 3 ] : " << BoxVolume ( 3 , 3 , 3 ) << std : : endl ; 이 라인
을 보면 함수 BoxVolume을 호출하면서 3개의 인자를 전달하고 있다. 따라서 디폴트 매개
변수는 전혀 의미가 없다.

std : : cout << " [ 5 , 5 , def ] : " << BoxVolume ( 5 , 5 ) << std : : endl ; 이 라인
에서는 함수 BoxVolume을 호출하면서 2개의 인자를 전달하고 있다. 잠깐 생각해 보자
이 두 개의 전달 인자는 각각 어디로 들어가겠는가 ? 함수 호출 시 전달되는 인자들은
무조건 왼쪽에서부터 채워지기 때문에 첫 번째 전달 인자 5는 매개 변수 length로 두 번째
전달인자 5는 매개 변수 width로 전달이 될 것이다. 그리고 마지막 매개 변수 height는
디폴트 매개 변수 1이 전달된 것으로 간주하게 된다.

" BoxVolume ( 5 , 5 ) " == " BoxVolume ( 5 , 5 , 1 ) "


std : : cout << " [ 7 , def , def ] : " << BoxVolume ( 7 ) << std : : endl ; 이
라인에서는 함수 BoxVolume을 호출하면서 1개의 인자만을 전달하고 있다. 따라서 다음과
같은 의미를 지니게 된다.

" BoxVolume ( 7 ) " == " BoxVolume ( 7 , 1 , 1 )"



< 3 디폴트 매개 변수와 함수의 오버로딩 >

디폴트 매개 변수와 함수 오버로딩을 동시에 잘못 정의하는 경우가 있다. 다음 예제를
보자. 그리고 문제점을 지적해 보자

# include < iostream >

int function ( int a=10 )
{

return a+1 ;

}

int function ( void )
{

return 10 ;

}

int main ( void )
{

std : : cout << function ( 10 ) << std : : endl ;
return 0 ;

}

위의 예제를 컴파일해 보면 컴파일도 잘 되고 실행도 잘 된다. 왜냐하면
int function ( int a=10 ) 이 라인에 정의된 함수 function과 int function ( void )
이 라인에 정의된 함수 function과의 관계는 어버로딩 관계이고 
std : : cout << function ( 10 ) << std : : endl ; 이 라인에서는 int형 데이터 하나
를 인자로 전달받는 함수 , 즉 이에 해당하는 함수를 호출하였으므로 문제될
것이 전혀 없다.

그러나 잠재적인 문제는 지니고 있다. 위의 예제에서 main 함수를 다음과 같이 변경한
다면 어떻게 될까 ?

int main ( void )
{

std : : cout << function ( ) << std : : endl ;
return 0 ;

}


자 ! 드디어 잠재적인 문제가 터지고 말았다. std : : cout << function ( ) << std : : endl ;
이 라인을 보면 function 함수를 호출하면서 인자를 전달하지 않고 있다. 그렇다면 어떤
함수를 호출 하겠는가 ? 문제는 위에서 정의한 두 함수 모두 호출 가능하다는데 있다.



위 그림처럼 컴파일러는 두 개의 함수 중에서 무엇을 호출해야 할 것인지를 결정짓지 못
한다. 따라서 에러를 발생시켜 버린다. 그러므로 이러한 형식의 함수 정의는 반드시 피해
야 한다.



★ 인-라인 ( in-line ) 함수 ★

in-line 함수의 의미부터 파악해 보자 in은 ' 내부 ' 를 의미하고 , line은 ' 프로그
램 라인 ' 을 의미하는 것이다. 즉 의역 해보면 " in-line 함수 " 란 프로그램 라인
안으로 들어가버린 함수라는 의미를 지닌다.


< 1 매크로 함수의 정의와 장점 >

우리는 C 언어를 공부하면서 매크로에 대해서 알게 되었다. 여기서는 이에 관련해서
잠깐 복습을 하기로 하자. 매크로를 이용하면 다양한 일을 할 수 있는데 그 중에서도
가장 대표적인 일은 함수를 만드는 것이다. 다음은 매크로를 이용해서 함수를 정의하고 이
를 호출하는 형태를 보여준다. 일반적인 순서에 의해서 전처리, 컴파일 링크 과정을 거쳐
서 실행 파일이 생성될 것이다.

# include < iostream >
# define SQUARE ( x ) ( ( x ) * ( x ) )

int main ( void )
{

std : : cout << SQUARE ( 5 ) << std : : endl ;
return 0 ;

}


그렇다면 위의 코드는 전처리 과정을 거치면서 어떻게 변하게 되는가 ? 다음 코드는 전처리
과정에 의해서 변경된 코드를 보여준다.

# include < iostream >

int main ( void )
{

std : : cout << ( ( 5 ) * ( 5 ) ) << std : : endl ;
return 0 ;

}


위의 두 코드를 통해서 알 수 있는 사실은 무엇인가 ? 그것은 함수를 매크로로 정의하면 전
처리기에 의해서 함수 호출 문장이 함수의 몸체 부분으로 완전히 대치돼 버린다는 것이다.
그렇다면 이를 통해서 얻게 되는 이점은 무엇인가? 함수 호출 과정이 사라졌기 때문에 성능
상의 이점을 맛볼 수 있다. ( 함수 호출은 스택 메모리 공간의 할당도 요구하며 시간도 많이
요구된다. )

위의 예제와 같이 함수 호출 문장이 함수의 몸체 부분으로 완전히 대치되 버리는 현상을
가리켜 " 함수가 inline 화되었다 " 라고 표현한다. 함수를 호출하는 위치에 함수의 몸체가
들어가 버렸으므로 아주 적절한 표현이다.

참고 => 매크로 함수에 대해서는 장점뿐만 아니라 단점도 알고 있어야 한다. 단점은
함수의 구현이 까다롭고 디버깅하기 어려우며 , 구현하고자 하는 함수의 크기가 크다면
프로그램의 크기가 된다는 것이다. 보다 자세한 사항은 C 언어 관련 서적을 참조하기
바란다.



< 2 C++ 기반 함수의 in-line 화 >

앞에서 매크로를 이용해서 함수를 in-line화하였다. 이처럼 매크로를 이용해서 C++의 함수
도 in-line화할 수 있다. 그러나 보다 쉬운 방법이 있다. 다음 예제 코드는 앞에서 본 예제를
C++ 스타일로 in-line화 하고 있다.

/*

inline . cpp

*/

# include < iostream >
inline int SQUARE ( int x )
{

return x * x ;

}

int main ( void )
{

std : : cout << SQUARE ( 5 ) << std : : endl ;
return 0 ;

}


inline int SQUARE ( int x ) 이 함수를 보자 함수를 정의하는 과정에서 키워드 inline을 붙
여준 것을 제외한다면 일반적인 함수와 다를 바가 없다. 그렇다면 여기서 붙여준 키워드
inline은 무엇을 의미하는 것일까? 이는 함수 SQUARE를 inline화 하라는 의미이다.

정리하자! C++에서는 성능 향상을 목적으로 함수를 inline화하기 위해서 매크로를 사용할
필요가 없다. 다만 inline이라는 키워드만 붙여주면 되는 것이다. 얼마나 간편하고 좋은가?

참고 => 매크로를 이용한 함수의 in-line화는 전처리기에 의해서 처리되지만 키워드 inline
을 이용한 함수의 in-line화는 컴파일러에 의해서 처리된다. 또한 컴파일러에 따라서는
inline 선언이 오히려 성능 향상에 해가 된다고 판단될 경우 , 그냥 무시해 버리기도 한다.



★ 이름공간 ( namespace )에 대한 소개 ★

이름공간이란 여러분에게 다소 생소한 개념이다. C 언어에는 존재하지 않는 개념이기 때문
이다. 그러나 어려운 개념은 아니다. 이름공간이란 이름을 지니는 공간이라는 뜻이다. 말
그대로 특정 영역( 공간 )에 이름을 붙여주기 위한 문법적 요소이다.


< 기본 원리 >

한 집에 철수라는 이름을 지니는 사람이 두 명 살고 있다면 이는 문제가 된다. " 철수야 "
라고 부르면 , 어떤 철수를 말하는지 구분 지을 수 없기 때문이다. 그러나 서로 살고 있는
집이 다르다면 문제될 것이 없다. 201호에 사는 철수와 202호에 사는 철수는 구분 지을 수
있기 때문이다. 다음과 같이 부르면 되지 않는가 ?

" 202호에 사는 철수야 ! "

이것이 이름공간의 기본 원리이다.


다음 예제는 앞에서 이야기한 문제점을 간략화해서 코드로 옮겨 놓은 것이다.
A와 B라는 이름의 회사가 구현한 프로그램 모듈을 하나의 완성된 프로그램으로 옮기는
과정에서 이름 충돌이라는 문제가 발생하였다.

# include < iostream >

void function ( void )
{

std : : cout << " A . com에서 정의한 함수 " << std : : endl ;

}


void function ( void )
{

std : : cout << " B . com에서 정의한 함수 " << std : : endl ;

}

int main ( void )
{

function ( ) ;
return 0 ;

}


A . com이라는 회사에서 정의한 함수가 다음 아래와 같이 정의되어 있고

void function ( void )
{

std : : cout << " A . com에서 정의한 함수 " << std : : endl ;

}

B . com이라는 회사에서 정의한 함수가 다음 아래와 같이 정의되어 있다.

void function ( void )
{

std : : cout << " B . com에서 정의한 함수 " << std : : endl ;

}

문제는 함수의 이름이 같다는 것이다. 따라서 컴파일 시 문제를 일으킬 것이다.
둘 다 필요한 기능의 함수라서 어느것 하나를 뺄 수도 없는 상황이다. ( 물론
그렇게 가정을 하자는 뜻이다. )

다음 예제에서는 이름공간을 정의해서 문제를 해결하고 있다. 일단 위의 예제와 어느
부분이 달라 졌는지 비교해서 실행해 보기 바란다.

/*

namespacel . cpp

*/

# include < iostream >

namespace A_COM
{

void function ( void )
{

std : : cout << " A . com에서 정의한 함수 " << std : : endl ;

}

}


namespace B_COM
{

void function ( void )
{

std : : cout << " B . com에서 정의한 함수 " << std : : endl ;

}

}

int main ( void )
{

A_COM : : function ( ) ;
B_COM : : function ( ) ;
return 0 ;

}

▶ 실행 결과

A . com에서 정의한 함수
B . com에서 정의한 함수


일단 위의 예제 namespace A_COM  이 부분의 함수를 보자 A라는 이름의 회사
에서 정의한 함수를 중괄호를 이용해서 감싸고 있다. 이것이 어떤 의미를 지니는지 다
음 그림을 통해서 설명하겠다.



위의 그림을 보면 namespace라는 키워드가 등장한다. 이는 이름공간을 구성하겠다는 의
미다. 즉 " namespace A_COM " 이라는 선언은 A_COM이라는 이름의 공간을 구성하겠
다는 의미가 되며, 이름공간의 범위는 이어서 등장하는 중괄호를 통해서 지정된다. 조금
더 쉽게 이야기를 하면 " 특정 영역( 공간 )의 범위를 지정하고 이름을 붙여준 것 " 이다.

따라서 위 그림에 선언되어 있는 함수 function은 A_COM이라는 이름공간 내에 선언이
된 것이다.

이제 다시 예제 namespace1 . cpp를 살펴보자 이 예제에서는 두 개의 이름공간이 등장
한다. 첫번째 이름공간은 namespace A_COM 이며, 두 번째 이름 공간은
namespace B_COM 이다. 이름공간의 내부에는 같은 이름의 함수가 정의되어 있다.
( 매개 변수의 타입까지도 같은 함수다 ). 그러나 문제되지 않는다. 왜냐하면 이름공간
이 다르면 같은 이름의 변수나 함수의 선언이 허용되기 때문이다. ( 201호에 사는
철수와 202호에 사는 철수의 예를 기억하자 ) .

한가지 주의할 것은 이름공간 내에 선언되어 있는 변수나 함수에 접근하는 방법이다. 위
의 예제 A_COM : : function ( ) ; 이 부분과 B_COM : : function ( ) ; 이 부분을
보자 다음과 같은 선언이 존재한다.

A_COM : : function ( ) ;


위 그림에서 : : 연산자를 가리켜 " 범위 지정 연산자 ( scope resolution operator ) " 라
한다. 즉 이름공간의 범위를 지정할 때 사용하는 것이다. 따라서 위 그림과 같은 선언은
다음과 같은 의미를 지니게 된다.

" A_COM이라는 이름공간 안에 선언되어 있는 function 함수를 호출하라 "

이렇듯 이름공간 안에 선언되어 있는 변수나 함수에 접근하기 위해서는 범위 지정 연
산자를 사용해서 선언되어 있는 이름공간을 지정해 줘야 한다. 이는 201호에 사는 철수
를 그냥 " 철수야 ! " 라고 부르지 않고 , " 201호에 사는 철수야 ! "라고 부르는 것과
같은 이치이다. 이제 예제 namespace1 . cpp가 이해될 것이다.

이번에 소개하는 예제는 namespace1 . cpp와 같은 예제이다. 다만 함수의 선언과 정의
를 분리시키는 방법을 보여줄 뿐이다. ( C 언어에서 함수는 보통 이렇게 구현하지 않았던가 ! )

/*

namespace2 . cpp

*/

# include < iostream >

namespace  A_COM
{

void function ( void ) ;

}

namespace  B_COM
{

void function ( void ) ;

}

int main ( void )
{

A_COM : : function ( ) ;
B_COM : : function ( ) ;
return 0 ;

}

namespace  A_COM
{

void function ( void )
{

  std : : cout << " A_COM에서 정의한 함수 " << std : : endl ;

}

}

namespace  B_COM
{

void function ( void )
{

  std : : cout << " B_COM에서 정의한 함수 " << std : : endl ;

}

}


namespace  A_COM
{

void function ( void ) ;

}

이 부분에서는 function이라는 이름의 함수를 A_COM이라는 이름공간 안에 선언만 하고
있다. 그리고

namespace  A_COM
{

void function ( void )
{

std : : cout << " A_COM에서 정의한 함수 " << std : : endl ;

}

}

이 부분에는 function이라는 이름의 함수를 A_COM이라는 이름공간 안에 정의하고 있다.
이처럼 함수의 선언과 정의를 분리하고자 하는 경우에는 같은 이름공간을 선언하고 그 내
부에 선언 및 정의해야 한다.

참고 => 위의 예제에서는 하나의 이름공간 안에 하나의 선언 및 정의만을 담고 있지만
실제로는 둘 이상의 선언 및 정의를 담을 수 있고 또 그것이 더 일반적이다.


< 3 std : : cout , std : : cin , std : : endl >

지금까지 입력 및 출력을 하고자 하는 경우에는 std : : cout 과 std : : cin을 사용해 왔다.
익것의 정체는 아직 모르지만 사용법만은 알고 있다. 그런데 이제는 조금 이해가 될 것이다.
: : 연산자가 어떠한 의미를 지니는지 이해했기 때문이다.

std : : cout은 무슨 의미인가 ? std라는 이름공간 안에 존재하는 cout을 참조하겠다는 의미
이다. 물론 우리는 아직 cout의 정체를 모르고 있다. 마찬가지로 std : : cin은 std라는 이름
공간 안에 존재하는 cin을 참조하겠다는 의미로 사용된다. 아마도 다음과 같은 그림이 머리
속에 그려질 것이다.

namespace  std
{

cout ???
cin ???
endl ???

}


즉 헤더 파일 iostream에 선언되어 있는 cout , cin 그리고 endl은 std라는 이름공간 안
에 선언되어 있다는 결론을 내릴 수 있다. 그래서 cout이나 cin을 참조할 때 " std : : "
라는 선언을 앞에다 붙여주는 것이다. 이름 충돌을 막기 위해서 C++ 표준에서 제공하
는 다양한 함수나 변수들을 이름공간 std 안에 선언 및 정의했기 때문이다.


< 4 using >

이제 cout , cin 그리고 endl을 참조할 때마다 " std : : "을 앞에다 붙여줘야 하는 이
유에 대해서 알게 되었다. 그리고 이 일이 여간 귀찮은 것이 아니라는 생각도 들기 시
작한다. 오히려 접근하고하 하는 이름공간에 대한 선언이 불필요한 과거의 표준이 더
맘에 끌리기도 한다. 하지만 걱정하지 말자. 추가적인 선언 하나만으로도 여러분의
이러한 불만사항을 해소할 수 있으니 말이다.

다음 예를 보자 중요한 것은 A_COM이라는 이름공간 안에 존재하는 함수를 범위 지정 ,
연산 없이 그냥 호출하고 있다는 것이다.

/*

using1 . cpp

*/

# include < iostream >

namespace  A_COM
{

void function ( void )
{

  std : : cout << " A_COM에서 정의한 함수 " << std : : endl ;

}

}

using  A_COM : : function ;

int main ( void )
{

function ( ) ;
return 0 ;

}

▶ 실행 결과

A_COM에서 정의한 함수


namespace  A_COM
{

void function ( void )
{

  std : : cout << " A_COM에서 정의한 함수 " << std : : endl ;

}

}
이 부분은 A_COM이라는 이름공간이 서언된 영역이며 그 안에 함수 function이 정의되어
있다.

using  A_COM : : function ; 이 부분의 선언은 다음과 같은 의미를 지닌다 " 앞으로
function이라는 이름을 참조하는 코드가 나오면 A_COM이라는 이름공간 안에 선언된
function이라는 이름을 참조하라 ! " 그래서 function ( ) ; 이 부분에는 단순히
function이라는 이름의 함수를 호출하고 있다. 컴파일러는 이 함수를 A_COM이라는 이름
공간 안에서 찾게 된다.

이번에는 위의 예제에서 소개한 선언을 이용해서 이전에 구현했던 HelloWorld2 . cpp를
조금 변경해 보겠다.

/*

HelloWorld3 . cpp

*/

# include < iostream >

using  std : : cout ;
using  std : : cin ;
using  std : : endl ;

int main ( void )
{

cout << " Hello World !! " << endl ;
cout << " Hello " << " World !! " << endl ;
cout << 1 << 'a' << " String " << endl ;
return 0 ;

}

▶ 실행 결과

Hello World !!
Hello World !!
1aString


이번에는 키워드 using을 이용한 또 다른 선언 방법을 소개하겠다. 다음 예제를 보자

/*

using2 . cpp

*/

# include < iostream >

namespace  A_COM
{

void function ( void )
{

  std : : cout << " A . com에서 정의한 함수 " << std : : endl ;

}

}

using namespace  A_COM ;

int main ( void )
{

function ( ) ;
return 0 ;

}

▶ 실행 결과

A . com에서 정의한 함수

이전 예제 using1 . cpp와 차이가 나는 부분은 using namespace  A_COM ; 이 부분이다
이는 다음과 같은 의미를 지닌다. " A_COM 안에 선언되어 있는 이름을 참조하는 경우에
는 ( 그것이 변수이건 함수이건 ) 이름공간에 대한 선언 없이 function ( ) ; 이와 같이
참조 하겠다.

이제 위의 예제를 참조해서 HelloWorld3 . cpp를 조금 변경해 보자 훨씬 간결해 보이면서
도 여러분들 마음에 들 것이다.

/*

HelloWorld4 . cpp

*/

# include < iostream >

using namespace std ;

int main ( void )
{

cout << " Hello World !! " << endl ;
cout << " Hello " << " World !! " << endl ;
cout << 1 << 'a' << " String " << endl ;

}

▶ 실행 결과

Hello World !!
Hello World !!
1aString

이제 using 선언에 대한 내용도 마무리를 지어 보자 !

당장 눈으로 보기에는 HelloWorld3 . cpp에 존재하는 using 선언보다
HelloWorld4 . cpp에 존재하는 using 선언이 좋아 보인다. 그러나 가급적이면
HelloWorld3 . cpp에 존재하는 using 선언을 이용하는 것이 좋다.

왜냐하면 이름공간 std 안에는 다양한 종류의 선언이 존재하는데 HelloWorld4 . cpp의
using namespace std ; 이 부분과 같은 선언을 넣어버리면 프로그래밍 하기에는 조금
편리하겠지만 이름 충돌이 발생할 확률은 상대적으로 높아지기 때문이다. 때문에 앞
으로 소개하는 예제에서는 조금 코드의 양이 많아지더라도 HelloWorld3 . cpp에 존재
하는 using 선언을 사용할 것이다.


< 5 또 다른 특징 >

지역 변수는 전역 변수의 이름을 가린다는 특징을 기억하는가? 다음 코드를 보자

int val=100 ;   // 1 번

int main ( void )
{

int val=100 ;  // 2번
val+=1 ;  // 3번
return 0 ;

}


위의 예제 1번 에는 val이라는 이름의 전역 변수가 선언되어 있고 2번에도 val이라는
같은 이름의 지역 변수가 선언되어 있다. 그렇다면 3번에 선언되어 있는 연산에 의해서
값이 1 증가되는 변수는 지역 변수와 전역 변수 중 어느 것이 되었는가 ? 당연히 2번에
선언된 지역 변수의 값이 1 증가하게 된다.

그렇다면 main 함수 내에서 전역 변수의 값을 1 증가시키고자 할 때에는 어떻게 해야
하겠는가 ? 우리는 이러한 경우에도 범위 지정 연산자를 사용할 수 있다.

int val=100 ;   // 1 번

int main ( void )
{

int val=100 ;  // 2번
: : val+=1 ;  // 3번
return 0 ;

}


위 3번을 보면 범위 지정 연산자가 등장하고 있다. 범위 지정 연산자의 왼편에는 접근
하고자 하는 이름공간 , 그리고 오른편에는 접근하고자 하는 변수 혹은 함수의 이름이
오게 되어 있다. 그런데 3번에는 범위 지정 연산자의 접근하고자 하는 이름공간이 존
재하지 않는다. 이것은 다음과 같은 의미를 지닌다.

" 전역 변수로 선언되어 있는 변수 val에 접근해라 "

결국 1번에 선언되어 있는 전역 변수 val의 값이 1증가하게 된다. 이처럼 범위 지정
연산자는 전역 변수에 접근하기 위한 용도로도 사용 가능하다.


- 연습 문제 -

문제 1

# include < iostream >

int main ( void )
{

int sum=0 ;
int num=0 ;

for ( int i=0 ; i<10 ; i++ )
{

std : : cout << " 입력 : " ;
std : : cin >> num ;
sum += num ;

}

std : : cout << " 합계 : " << sum << std : : endl ;
return 0 ;

}



문제 2

# include < iostream >

int main ( void )
{

char name[ 20 ] ;
char phone[ 20 ] ;

std : : cout << " 이름 입력 : " ;
std : : cin >> name ;

std : : cout << " 전화번호 : " ;
std : : cin >> phone ;

std : : cout << " 이름 : " << name << std : : endl ;
std : : cout << " 전화번호 : " << phone << std : : endl ;

return 0 ;

}


문제3

# include < iostream >

int main ( void )
{

int num ;

std : : cout << " 숫자 입력 : " ;
std : : cin >> num ;

for ( int i=1 ; i<10 ; i++ )
{

std : : cout << num << 'x' << i << '=' << num*i << std : : endl ;

}

return 0 ;

}


문제4

# include < iostream >

double CalSalary ( double sales ) ;

int main ( void )
{

double sales ;

while ( 1 )
{

std : : cout << " 판매 금액을 만원 단위로 입력 ( -1 to end ) : " ;
std : : cin >> sales ;
if ( sales == -1 )
break ;

std : : cout << " 이번 달 급여 : " ;
std : : cout << CalSalary ( sales ) << " 만 원 " << std : : endl ;

}
return 0 ;

}

double CalSalary ( double sales )
{

return 50+sales*0.12 ;

}


문제5

# include < iostream >

void swap ( int *a , int *b ) ;
void swap ( char *a , char *b ) ;
void swap ( double *a , double *b ) ;

int main ( void )
{

int num1=20 , num2=30 ;
swap ( &num1 , &num2 ) ;
std : : cout << num1 << ' ' << num2 << std : : endl ;

char ch1 = 'a' , ch2 = 'z' ;
swap ( &ch1 , &ch2 ) ;
std : : cout << ch1 << ' ' << ch2 << std : : endl ;

double db1 = 1.111 , db2 = 5.555 ;
swap ( &db1 , &db2 ) ;
std : : cout << db1 << ' ' << db2 << std : : endl ;

return 0 ;

}

void swap ( int *a , int *b )
{

int temp=*a ;
*a=*b ;
*b=temp ;

}
void swap ( char *a , char *b )
{

char temp=*a ;
*a=*b ;
*b=temp ;

}
void swap ( double *a , double *b )
{

double temp=*a ;
*a=*b ;
*b=temp ;

}