함수에 대해서 설명한 이전 포스트에서 함수 정의부에 명시된 입력 변수의 개수보다 적은 입력변수를 함수에 넘겨주는 경우 못받은 변수는 생성이 되지 않으므로 이를 따로 처리해야 한다고 하였다. 그렇다면 함수 내부에서 입출력 변수의 개수를 어떻게 알아낼 수 있을까? 이 작업을 위해서 nargin변수와 nargout변수가 마련되어 있다. 이 변수들은 모두 정수값을 가지며, nargin변수는 호출된 함수 내부에서 그 함수로 인가된 입력 변수의 개수값을 가지고 nargout 변수는 출력 변수의 개수를 가진다. 이들 변수값을 이용하여 여러 가지 입출력 방법에 대해서 대처를 할 수 있다. 앞에서 예를 든 mimo()함수를 다음과 같이 수정해 보자.


1 : function [y1,y2]=mimo2(x1,x2,x3)
2 : % function [y1,y2]=mimo(x1,x2,x3)
3 : % y1은 입력변수들의 합
4 : % y2는 입력변수들의 곱
5 : if (nargin==1)
6 :     y1=x1;
7 :     y2=x1;
8 : elseif (nargin==2)
9 :     y1=x1+x2;
10:     y2=x1*x2;
11: elseif (nargin==3)
12:     y1=x1+x2+x3;
13:     y2=x1*x2*x3;
14: else
15:    y1 = 0;
16:    y2=0;
17: end


이 수정된 함수에서 5번 줄과 8번 줄 그리고 11번 줄에서 nargin변수가 사용이 되었다. nargin==1이 참이라면, 즉 입력변수가 하나라면 6번 줄과 7번 줄을 수행시킨다. nargin==2이 참이라면, 즉 입력변수가 두개라면 9번 줄과 10번 줄을 수행시킨다. nargin==3이 참이라면, 즉 입력변수가 세 개라면 12번 줄과 13번 줄을 수행시킨다. 마지막으로 모든 경우가 거짓이라면, 즉 입력 변수가 없다면 15, 16번 줄을 수행시킬 것이다. 입력변수가 4개 이상이라도 else 문에 걸려서 15,16번 줄이 수행된다.


>> [x,y]=mimo2()
x = 0
y = 0
>> [x,y]=mimo2(11)
x =  11
y =  11
>> [x,y]=mimo2(11,22)
x =  33
y =  242
>> [x,y]=mimo2(11,22,33)
x =  66
y =  7986
>> [x,y]=mimo2(11,22,33,44)
x = 0
y = 0


연습삼아서 이 mimo2()함수를 switch-case문을 이용하여 수정해 보기 바란다.


'프로그래밍언어.Lib > MATLAB' 카테고리의 다른 글

MATLAB의 함수 m파일  (0) 2015.07.16
MATLAB의 break, continue 명령  (0) 2015.07.16
MATLAB의 반복문 while ~ end  (0) 2015.07.14
MATLAB의 반복문 for ~ end  (0) 2015.07.14
MATLAB의 조건문 switch ~ case ~ end  (0) 2015.07.13
Posted by 살레시오
,

 스크립트 m파일과 구별되는 다른 형태의 파일로서 함수(function) m파일이 있다. 지금까지 자주 사용해왔던 sin(), cos(), exp()같은 함수를 생각해 보면 사용자는 입력값을 이들 함수에 넘겨주고, 예를 들어 sin(pi)명령은 pi라는 값을 sin()함수에 넘겨주고 그 결과값 0을 얻게 된다. 내부적으로 어떠한 계산 과정이 있는 지는 일반 사용자는 알 필요가 없고 단지 입력에 대한 결과값을 얻을 뿐이다. 이와 같이 미리 정의된 함수 외에 사용자만의 함수를 작성할 수도 있다.


 함수 m파일은 입력 값과 출력 값이 존재하며 입력 변수를 받아서 특정한 기능이나 계산 등을 수행한 다음 그 결과 값을 반환하는 기능을 한다. 스크립트 m파일의 경우 생성된 변수들이 작업 공간에 위치하는 것과는 대조적으로 함수 m파일은 함수 내에서 사용된 변수들이 작업 공간과는 별도의 메모리 공간을 사용하며 함수의 수행이 끝나면 그 메모리 공간도 사라진다. 단지 출력 값만을 그 함수가 호출된 곳으로 반환시켜줄 뿐이다.

다음의 예제를 입력하여 보자.


function Y = flipud(X)
   [m,n] = size(X);
   Y = X(m:-1:1,:);


그리고 이 파일을 ‘flipud.m'으로 저장하자. 이 함수는 행렬 x를 받아서 행들의 순서를 역순으로 바꾼 후 출력하는 기능을 하는 함수이다. 이제 명령창에서 다음과 같이 명령을 내려보자.


>>A=rand(3,2) 󰎠
A =
0.0187 0.9737
0.3107 0.5865
0.7713 0.6441

>>B=flipud(A) 󰎠
0.7713 0.6441
0.3107 0.5865
0.0187 0.9737


위에서 입력 행렬 A의 행의 순서가 바뀌어서 반환된 것이 B에 저장됨을 알 수 있다. 또한 함수 내부에서 사용된 변수 m,n은 작업 공간에 나타나지 않음도 변수창에서 확인할 수 있다. 작업 공간에는 출력변수 B만이 생성되는 것이다.


 함수 m파일은 첫 번째 줄은 이 M파일이 함수라는 것을 나타내는 키워드 'function' 과 출력 변수, 함수 이름, 입력 변수 등으로 구성되며 문법은 다음과 같다.


function [y1, y2, …] = fname(x1, x2, …)


함수의 이름 fname은 m파일의 이름과 되도록이면 같도록 해야 한다. 만약 다르면 m파일의 이름이 우선하게 된다. 함수의 입출력 변수는 여러 개일 수도 있고 하나도 없을 수도 있다. 또한 함수의 정의부에 선언된 입출력 변수보다 적은 수의 변수로 함수를 호출할 수 있지만 더 많은 수의 입출력 변수를 지정하면 에러가 발생하게 된다. 다음의 예를 보자.


function [y1,y2]=mimo(x1,x2,x3)
% function [y1,y2]=mimo(x1,x2,x3)
% y1은 입력변수들의 합
% y2는 입력변수들의 곱
y1=x1+x2+x3;
y2=x1*x2*x3;


이 함수는 입력이 3개이고 출력이 2개인 함수이며 출력 y1은 입력들의 함을, y2는 입력들의 곱을 계산한다. 함수 정의부 밑에 ‘%’로 시작하는 문장들은 주석문으로서 M파일에서 '%'뒤에 오는 것들은 무시하며 실행하지 않으므로 이 기호 뒤에 설명문을 위치시키면 된다. 함수의 선언문과 첫 번째 실행문 사이의 주석문은 단순한 주석문이 아니라 명령창에서 help명령을 수행시켰을 때 보여주는 문장들이다. 명령창에서 다음을 수행해 보자.


>>help mimo 󰎠
function [y1,y2]=mimo(x1,x2,x3)
y1은 입력변수들의 합
y2는 입력변수들의 곱


이제 이 함수를 실행시켜 보자. 함수 정의부에서 출력 변수는 두 개로 지정이 되었지만 함수를 호출할 때는 출력변수를 0개, 1개, 2개 모두 지정할 수 있으며 3개 이상을 지정하면 에러가 발생한다.


>>mimo(3,4,5)
y1 =
12

>>y1=mimo(3,4,5)
y1 =
12

>>[y1,y2]=mimo(3,4,5)
y1 =
12
y2 =
60

>>[y1,y2,y3]=mimo(3,4,5)
-----------------------------------
* MATLAB 디버그 정보 (오류 발생) *
-----------------------------------
파일 이름 : C:\MATLAB_MFILES\mimo.m
라인 번호 : 1 --> function [y1,y2]=mimo(x1,x2,x3)
오류 내용 : 함수의 입출력 갯수가 올바르지 않습니다.


위에서 알 수 있듯이 출력 변수를 지정하지 않으면 첫 번째 출력 변수만을 화면에 보여준다. 그리고 출력 변수를 하나만 지정하면 두 번째 출력변수는 반환되지 않게 된다.

입력 변수도 아예 지정하지 않거나 한 개나 두 개만 입력할 수 있지만 함수 내에서 넘겨받지 않은 변수는 생성되지 않게 되므로 함수 실행 시 에러를 발생하게 된다.


>> mimo(3,4)
-----------------------------------
* MATLAB 디버그 정보 (오류 발생) *
-----------------------------------
파일 이름 : C:\MATLAB_MFILES\mimo.m
라인 번호 : 5 --> y1=x1+x2+x3; %...
오류 내용 : x3라는 변수나 함수가 없습니다. 이름이 맞는지 확인하십시요.


위의 경우는 세 번째 입력변수를 넘겨주지 않았으므로 mimo함수 내부적으로 x3라는 변수 자체가 없어서 덧셈을 수행하지 못하게 되는 것이다. 즉 적은 수의 입력 변수를 넘겨주는 것은 문법적으로 허용이 되지만 넘겨받지 못한 변수를 생성하기 위한 추가적인 실행문이 필요하게 된다. 이에 대해서는 다른 포스트에서 자세히 설명하겠다.





Posted by 살레시오
,

 익명 함수(lambda function)란 말 그대로 이름이 없는 함수이며 파이썬에서는 lambda 라는 키워드로 익명 함수를 정의할 수 있다. 주로 비교적 간단한 기능의 함수가 컨테이너의 요소로 들어가는 경우 혹은 다른 함수의 인자로 함수를 넘겨줄 필요가 있을 때 사용된다.


익명 함수는 다음과 같이 생성된다.


lambda 인자1,인자2, … : 표현식


익명 함수는 보통 한 줄로 정의된다. return문도 없으며 단지 인자들과 반환값들의 관계식으로만 표현된다. 예를 들어 두 수의 합을 반환하는 익명 함수는 다음과 같다.


>>> add = lambda a, b : a+b
>>> add(1,2)
3


이 익명 함수는 다음과 같이 일반 함수를 정의하는 것과 동일하다.


>>> def add(a, b) :
…..      return a+b
>>> add(1,2)
3


그렇다면 일반 함수와 익명 함수와의 차이점은 무엇인가? 익명 함수의 기능은 일반 함수보다도 훨씬 제한적이고 익명 함수로 할 수 있는 것은 일반 함수로도 모두 할 수 있다. 그렇다면 왜 익명 함수를 사용할까?


때로는 굳이 번거롭게 일반 함수를 정의할 필요가 없는 간단한 기능만을 구현해도 되는 경우가 있다.  예를 들어서 입력 인수가 0보다 크면 True를 반환하는 함수를 생각해 보자.


>>> def pos(x):
…..    return x>0
>>> list(filter(pos, range(-5,6)))
[1,2,3,4,5]


이것을 익명 함수를 이용하면 다음과 같이 간단하게 처리할 수 있다.


>>> list( filter(lambda x:x>0, range(-5,6)) )
[1,2,3,4,5]


또는 다음과 같이 간단한 함수들을 리스트의 요소로 지정할 경우도 있을 것이다.


>>> fl = [lambda x,y:x+y, lambda x,y:x*y]
>>> fl[0](1,2)
3
>>> fl[1](3,4)
12


이와 같이 람다 함수의 용도는 보다 간결하게 원하는 기능을 수행할 수 있도록 하는 것이다.



Posted by 살레시오
,

 파이썬 함수의 기본값 인자(default parameter)란 함수를 호출할 때 인자의 값을 설정하지 않아도 기본값이 할당되도록 하는 기능이다. 기본값은 함수를 정의할 때 지정해준다. 예를 들어 보자.


def funcA(a=10):
   print('a='+str(a))


이 함수는 다음과 같이 두 가지 방법으로 호출할 수 있다.


>>> funcA() # a에 기본값인 10이 자동으로 저장된다.
a=10
>>> funcA(20) #a에 20이 전달된다.
a=20


이 예에서 인자 a는 기본값 인자이고 호출하는 쪽에서 값을 주지 않으면 기본적으로 10 값을 갖게 된다. 그래서 funcA()와 같이 값을 주지 않으면 10이 출력되고 funcA(20)과 같이 값을 주면 그 값이 인자 a 로 전달되는 것이다.


 다른 예를 들어 보자.


def printName(firstName, secondName='Kim'):
   print('My name is '+ firstName +' ' + secondName +'.')


이 함수도 다음과 같이 두 가지 방법으로 호출 가능하다.


>>> printName('Jang-Hyun')
My name is Jang-Hyun Kim.
>>> printName('Jang-Hyun', 'Park')
My name is Jang-Hyun Park.


기본값 인자는 값을 생략해서 호출할 수 있지만 일반 인자는 반드시 값을 지정해 주어야 한다. 따라서 printName()함수를 호출할 때 첫 문자열은 반드시 정해서 넘겨주어야 한다. 여기에서 printName()함수의 두 번째 인자를 입력하지 않으면 기본적으로 ‘Kim’으로 지정된다. 두 번째 인자를 명시적으로 지정하면 그것이 secondName 으로 지정된다.


 한 가지 주의할 점은 일반 인자와 기본값 인자가 같이 올 때에는 반드시 기본값 인자는 뒤에 와야 한다는 점이다. 즉, 아래와 같이 정의하면 오류가 발생한다.


>>> def printName(firstName='Kim', secondName):


기본값 인자가 두 개 이상일 때에서도 항상 일반 인자 뒤에 와야 한다.


>>> def add(a, b=0, c=0):
...     return a+b+c
...
>>> add(1)
1
>>> add(1,2) # b에 2가 들어간다.
3
>>> add(1,2,3) # b에 2, c에 3이 들어간다.)
6


이 예에서 보듯이 함수를 호출할 때 주는 순서 대로 기본값 인자에 값이 할당 됨을 알 수 있다.


 또 한 가지 주의할 점은 기본 인자는 최초의 호출 시에만 지정된 값으로 초기화 되고 이후의 호출에서는 그렇지 않다는 점이다. 따라서 리스트나 딕셔너리와 같은 가변(muatble) 객체를 기본 인자로 사용할 때 문제가 된다.


>>> def f(a, L=[]):
...     L.append(a)
...     return L
...
>>> f(1)
[1]
>>> f(2)
[1, 2]
>>> f(3)
[1, 2, 3]


이 예제를 보면 기본 인자 L은 최초의 호출에서만 빈 리스트로 초기화 되고 그 이후의 호출에서는 그 내용물은 유지된다. 따라서 리스트의 요소가 축적되는 것이다. (마치 C/C++에서의 static 변수와 비슷한 동작을 수행한다.)


 후속 호출에도 mutalbe 객체를 초기화하려면 다음과 같은 방법으로 코딩하면 된다.


def f(a, L=None):
   if L is None:
       L = []
   L.append(a)
   return L


이 경우 실행 결과는 다음과 같다.


>>> f(1)
[1]
>>> f(2)
[2]
>>> f(3)
[3]




Posted by 살레시오
,

 함수(function)란 실행문들을 묶어서 하나의 블럭으로 만든 후 이름을 붙인 것을 말한다. 이렇게 수행문들의 집합을 함수로 정의하면 그 수행문들을 동작시킬 때 함수 이름을 이용한 간단한 호출(call)로 반복해서 실행시킬 수 있다.


 파이썬 함수는 다음과 같이 정의된다.


def 함수명(인자1, 인자2, …):
함수 본체


함수의 정의는 항상 def로 시작한다. 함수명은 일반적인 식별자를 사용하며 관례적으로 (변수명과 마찬가지로) 소문자로 시작한다. 그다음에 호출하는 쪽에서 넘겨 받을 인자들의 리스트를 괄호(...)안에 콤마로 구별하여 지정해 주고 콜론(:) 뒤에 함수의 본체를 작성해 주면 된다. 함수의 본체는 반드시 def 의 첫 글자 시작 위치보다 들여 써야 한다.


 간단한 예를 들어보자


>>> def sayHi():
print(‘hi’)


이 함수는 ‘hi’라는 문자열을 출력하는 함수이며 함수의 이름은 sayHi()이다. 입력 인자는 없으며 반환값도 없다. 이 함수를 호출하려면 다음과 같이 하면 된다.


>>> sayHi()
Hi


구구단을 출력하는 함수를 예로 들어보자.


>>> def gugu(n):
...     for x in range(2,10):
...         print('%d x %d = %d'%(n,x,n*x))


이 함수는 하나의 입력 인자를 받도록 되어 있다. 다음과 같이 호출한다.


>>> gugu(4)
4 x 2 = 8
4 x 3 = 12
4 x 4 = 16
4 x 5 = 20
4 x 6 = 24
4 x 7 = 28
4 x 8 = 32
4 x 9 = 36

>>> gugu(8)
8 x 2 = 16
8 x 3 = 24
8 x 4 = 32
8 x 5 = 40
8 x 6 = 48
8 x 7 = 56
8 x 8 = 64
8 x 9 = 72


함수명은 함수객체이며 다른 객체와 유사하게 대입이 가능하다. 예를 들어 앞에서 정의한 함수 sayHi()와 gugu()를 하나의 리스트로 묶을 수 있다.


>>> fl = [sayHi, gugu]


여기서 fl 리스트의 첫 번째 요소는 함수 sayHi 이고 두 번째 요소는 gugu 이다. 따라서 다음과 같은 함수 호출이 가능하다.


>>> fl[0]()
Hi.
>>> fl[1](9)
9 x 2 = 18
9 x 3 = 27
9 x 4 = 36
9 x 5 = 45
9 x 6 = 54
9 x 7 = 63
9 x 8 = 72
9 x 9 = 81



또는 함수를 다른 변수에 대입할 수도 있다.


>>> kuku = gugu


이제 kuku 는 함수이며 gugu()함수와 같은 함수이다. 따라서 다음과 같이 동일하게 호출할 수도 있다.


>>> kuku(7)
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63


 가끔 함수의 본체를 구현하지 않고 껍데기만 작성해야 될 경우도 있다. 이럴 경우 다음과 같이 하면 된다.


>>> def nop(): pass


이 함수는 호출은 할 수 있으나 아무런 일도 수행하지 않는다.



Posted by 살레시오
,

C++에서 함수의 인자 전달

C언어,C++,함수,인자,function,argument,전달



 함수는 인자(argument)를 통해서 기능 수행에 필요한 값들을 전달 받는다. 또한 함수는 결과값을 반환하는 경우도 있고 반환 값이 없는 함수도 있다. 이렇게 함수와 호출자 사이의 정보 교환은 인자반환값이라는 매개체를 통해서 이루어진다.


  • 인자(argument) : 함수가 값을 받는 매개 변수

  • 반환값(return value) : 함수가 되돌려 주어야 할 수행 결과값


C++ 언어에서 함수 인자 전달 매커니즘을 한 번 살펴보도록 하자.


//호출부
int main() {
   int is = add(ix, 20); //① ix, 20은 실인자
}

//피호출부
int add(int ia, int ib) { //② ia, ib 값은 가인자
   int isum = ia + ib;
   return isum;
}


호출하는 함수의 인자를 실제 값이라는 의미로 실인자라고 하고 호출되는 함수에서는 가인자라고 한다. 실인자와 가인자 사이에 데이터를 넘겨주는 방식은 값에 의한 호출(call-by-value) 방식으로서 실인자의 값이 복사되어 넘겨진다.


 호출되는 함수의 return 명령은 이 함수가 내부적으로 연산을 수행한 후 반환값이 있다면 그 뒤에 반환값을 두게 된다. 반환값이 없다면 return문만 단독으로 사용한다. 입력 인자는 없을 수 도 있고 여러 개일 수 있지만 반환값은 없거나 한 개뿐이다.


 위의 예제에서처럼 호출하는 함수는 반드시 main()함수이어야 되는 것은 아니다. 어떤 함수에서든지 다른 함수를 자유롭게 호출할 수 있다. 심지어 어떤 함수 내부에서 그 함수 자체를 호출할 수도 있으며 이를 재귀 호출(recursive call)이라 한다.


사용자 함수를 작성하여 사용하려면 다음과 같은 단계를 따른다.


  1. 함수의 기능 및 인자, 반환값을 설계한다.

  2. 정해진 형식에 따라 함수를 선언한다.

  3. 함수의 본체 부분을 작성한 후 (정의) 호출하여 사용한다.

  4. 호출하는 쪽의 인자의 개수와 형식 그리고 반환값의 형식이 모두 정의된 대로여야 한다.


 앞에서도 언급했지만 C/C++ 언어의 값에 의한 호출 방식은 호출부와 피호출부의 인자들 사이의 관계에서 값만을 전달하는 방식으로 데이터값을 복사하여 전달한다. 이는 문서를 복사했을 때 복사본을 아무리 수정해도 원본이 변하지 않는 것과 같은 원리이다.


 다음 예를 보자.


//호출부:
int main() {
   int ia = 10, ib = 10, ic;
   ....
   ic = sub(ia, ib); //❶
   ....
   printf(“%d”,ia);
}

//피호출부:
int sub(int ia, int ib) { //❷
   ia -= ib;
   return ia;
}


호출부 ❶에서의 변수 ia, ib와 피호출부 ❷에서의 변수 ia, ib는 변수명은 같으나 저장 공간이 다른 완전히 다른 변수라는 점을 유의해야 한다. sub()함수 내부에서 ia값은 바뀌지만 그렇다고 main()함수 안의 변수 ia가 바뀌는 것은 아니다. 서로 다른 변수이기 때문이다.


호출부에서 반환값을 받을 때도 피호출된 함수에서 반환값이 복사되어 새로운 변수를 통해 전달된다. 즉, return ia; 실행문에 의해서 ia변수의 '값'이 복사되어 호출부의 변수 ic에 전달되는 것이다. 이것이 값에 의한 호출 방식의 동작 원리이다.


C++ 강좌 전체 목록 >>>


c{c++},n{c0015}


Posted by 살레시오
,

 명령어 return은 함수 내부에서 사용되어 함수의 실행을 끝내는 역할을 한다. return 다음에는 반환값이 오기도 하고 void형 함수의 경우는 반환값이 없이 단독으로 사용된다.


  • return; // void형 함수의 종료

  • return 반환값; // 반환값이 있는 함수의 종료 및 결과값 반환


이 명령은 또한 함수 실행 도중에 강제로 수행을 종료하려는 목적으로 사용할 수 있다.


void sayHi() {
 printf("Hi ");
 return;
 printf("all."); //절대 실행되지 않는다.
}


이 예에서 두 번째 printf()함수는 절대로 실행되지 않는다. return명령어에 의해서 함수의 실행이 종료되기 때문이다.


long factorial(long n){
 if (n<0) return -1;
 long lf = 1;
 while(n>1) {
   lf *= n--;
 }
 return lf;
}


이 함수는 만약 인자의 값이 음수라면 -1을 반환하고 바로 종료되어 버린다. 그렇지 않다면 팩토리얼을 구해서 반환한다.


 또 다른 예를 살펴보자. 함수 exec()는 char형을 받아서 char형을 반환한다. main()함수에서는 사용자로부터 숫자를 하나 입력 받아서 cn 변수에 대입한 후 그것을 exec()함수의 인자로 넘겨주면서 호출하도록 되어 있다. ❶줄을 보면 조건 검사를 하기위해서는 exec()함수를 호출해야만 하도록 되어있다. exec()함수 내부에서 보면 만약 입력한 인수가 1,2,3 셋 중 하나가 아니라면 ❷번 줄의 return –1; 명령에 의해서 함수의 수행이 바로 종료되게 된다. 1, 2, 3중 하나라면 해당되는 명령을 수행했다는 표시를 하게 된다. main()함수에서는 이 함수의 반환값이 –1이라면 수행이 제대로 안 되었다고 판단하고 “Execution failed.”라는 메세지를 표시한다. 또한 반환값이 1이라면 정상적으로 명령이 수행되었다고 판단할 수도 있다. 이 예에서와 같이 함수 내에서 return명령을 만나면 그 즉시로 함수는 종료되게 된다.


#include <stdio.h>

char exec(char);

int main(void) {
  char cn;
  printf("1. Turn left.\n");
  printf("2. Turn right.\n");
  printf("3. Stop.\n");
  printf("Command : ");
  scanf("%d", &cn);
  if (exec(cn)==-1) //❶
      printf("Execution Failed.\n");
}

char exec(char ca) {
  if (ca!=1 && ca!=2 && ca!=3)
      return –1; //❷

  switch (ca) {
      case 1:
          printf("Robot turned left.\n");
          break;
      case 2:
          printf("Robot turned right.\n");
          break;
      case 3:
          printf("Robot stopped.\n");
          break;
  }
  return 1;
}


직접 실행해 보고 결과를 확인해 보기 바란다.


C++ 강좌 전체 목록 >>>


c{c++},n{c0026}


Posted by 살레시오
,

 이전 포스트에서는 사용자 정의 함수가 main()함수 이전에 위치하였다. 또 다른 예를 들어보자.


double getArea(double dr) { //반지름으로 원의 면적을 구하는 함수
   double dArea = 3.14*dr*dr;
   return dArea;
}

int main() {
   double da = getArea(5.0);
}


하지만 C++ 프로그램은 관례적으로 main()함수를 다른 함수들보다 위에 위치시킨다. 맨 먼저 실행되는 함수이기도 하지만 이렇게 배치해야 다른 함수들과 호출 순서나 상관 관계를 파악하기 쉽다.


  하지만 다음과 같이 단순히 순서를 바꾸기만 해서는 문제가 생긴다.


int main() {
   double da = getArea(5.0); //문제 발생
}

double getArea(double dr) {
   double dArea = 3.14*dr*dr;
   return dArea;
}


왜냐면 컴파일을 수행할 때 main()함수 내부의 함수 호출 getArea() 을 처리하는 시점에서 이 함수에 대한 어떠한 정보도 없기 때문이다. 이렇게 하면 컴파일러는 오류를 발생시킨다.


 이런 경우 함수에 기본적인 정보를 주는 부분이 main()함수 위에 와야 하는데 이것을 ‘함수의 선언’ 이라고 한다. 함수의 선언은 함수 정의부에서 본체를 제외한 첫 줄만 따로 적어주면 된다.

  

double getArea(double dr); //함수의 선언

int main() {
   double da = getArea(5.0);
}

double getArea(double dr) { //함수의 정의 (본체 포함)
   double dArea = 3.14*dr*dr;
   return dArea;
}


이렇게 하면 컴파일시에 오류를 발생시키지 않는다. 이와 같이 함수의 정의가 호출하는 부분보다 뒤에 온다면 반드시 함수의 선언이 선행되어야 한다.


실행 가능한 전체 프로그램을 다음과 같다.


#include <stdio.h>
double getArea(double);

int main(int argc, char **argv) {
   double da = getArea(5.0);
   printf("Area: %f", da);
}

double getArea(double dr) {
   double dArea = 3.14 * dr * dr;
   return dArea;
}
//실행결과
78.500000


함수의 선언과 정의의 차이점을 다시 한 번 살펴보자.


  • 정의(definition) : 사용자가 만든 함수의 본체 부분까지 실제로 구현된다. 따라서 컴파일러가 함수 본체를 저장할 메모리를 당연히 확보하고 호출부보다 먼저 위치한다면 선언과 겸할 수 있다.


  • 선언(declaration) : 컴파일러에게 사용자가 만든 함수의 인자와 반환 자료형을 미리 알려준다. 컴파일러가 본체를 위한 메모리를 확보하지는 않는다 선언은 정의를 겸할 수 없다.


 함수의 선언에서 인자의 변수명은 생략할 수 있으나 인자의 자료형을 반드시 명시해주어야 한다. 다음 예를 보자.


#include <stdio.h>

int add(int, int);

int main() {
  int ia = 100, ib=150;
  int isum1, isum2;
  isum1 = add(10,20);
  isum2 = add(ia, ib);
  add(10, isum1);
  printf("%d, %d\n", isum1, isum2);
}

int add(int ix, int iy) {
  return ix+iy;
}

실행결과

30, 250


이 예제에서 함수 add()의 선언에서 인자의 변수명을 생략했음을 알 수 있다. 이렇게 해도 문법적으로 오류가 발생하지 않는다.


C++ 강좌 전체 목록 >>>


c{c++},n{c0014}

'프로그래밍언어.Lib > C,C++' 카테고리의 다른 글

C++에서 함수의 인자 전달  (0) 2015.05.18
C++ 의 return 명령어  (0) 2015.05.18
C++ 사용자 함수(function)의 정의  (0) 2015.05.17
C/C++ 함수(function) 개요  (0) 2015.05.17
C++ 클래스 예제 : Led 클래스  (0) 2015.05.17
Posted by 살레시오
,

 C++ 언어의 함수는 크게 반환값이 있는 함수와 반환값이 없는 함수 두 가지로 나눌 수 있다. 반환값이 있는 함수는 함수가 호출(call)이 되어 뭔가 작업을 거친 후 호출한 위치로 그 기능을 수행한 결과 값을 다시 보낸다. 반환값이 없는 함수는 단순히 어떤 기능만 수행한다는 것을 의미한다.


예를 들어서 두 개의 입력 값을 받아서 더한 값을 돌려 주는 기능을 하는 함수를 생각해 보자. 이 때 입력되는 값은 ‘인자’(argument) 혹은 ‘매개변수’(parameter)라고 부른다. (이후에는 ‘인자’ 라는 명칭만을 사용할 것이다.) 계산 결과값(이 경우 더한 값)을 호출한 곳으로 되돌려주는 경우 이것을 ‘반환값’, ‘리턴값’이라고 한다.


  • 인자(argument) - 함수로 넘겨주는 데이터

  • 반환값(return value)  - 함수가 작업이 끝나고 넘겨주는 결과값


사용자 정의 함수는 문자 그대로 ‘사용자가 필요에 의해서 만드는 함수’를 의미한다. C++ 프로그램에서 함수를 사용하기 전에 반드시 정의를 해 주어야 한다. 함수의 정의 형식은 다음과 같다.


반환자료형 함수명(데이터형 인수1, 데이터형 인수2 ...) {
   함수 본체
}


예를 들면 다음과 같다.


void sayHi() {
   printf("Hi ");
   printf("all.");
}


이 함수의 이름은 sayHi()이다. 함수명 앞에는 이 함수의 반환 값의 데이터 형을 명시한다. 반환값이 없는 경우에는 명시적으로 void라는 키워드를 써야 한다. 이 함수는 인자가 없다. 이렇게 인자가 없는 경우 함수명 뒤에 그냥 빈 괄호를 입력한다. 괄호를 생략할 수 없음에 유의하자.


이렇게 정의된 함수는 다음과 같이 호출할 수 있다.


int main() {
   ...
   sayHi(); // sayHi()함수 호출
   ...
}


이것을 합하여 완전한 프로그램으로 만들면 다음과 같다.


#include <stdio.h>

void sayHi()
{
   printf("Hi ");
   printf("all.");
}

int main(int argc, char **argv)
{
  sayHi();
}


Hi all.


이 프로그램을 보면 sayHi() 함수와 main() 두 개의 함수가 있다. 이 예제가 실행될 때는 항상 main()함수를 실행시키며 main()함수가 종료되면 프로그램도 종료된다. C++ 언어는 항상 main()함수를 제일 먼저 실행시킨다.


또 다른 함수의 예를 들어보자.


void sayHello(int in)
{
   for(;in>0;in--) {
       printf(“Hello.\n”);
   }
}


이 함수는 반환값이 없으며 인자를 하나 받는 함수이다. 그렇게 받은 인자의 개수만큼 “Hello.”를 반복해서 출력하는 일을 한다. 이것으로 완전한 프로그램을 만들어 보면 다음과 같다.


#include <stdio.h>

void sayHello(int in)
{
   for(;in>0; in--){
       printf("Hello. ");
   }
}

int main(int argc, char **argv)
{
   sayHello(3);
   int ia = 5;
   sayHello(ia);
}


Hello. Hello. Hello.
Hello. Hello. Hello. Hello. Hello.


main()함수 내에서 sayHello()함수를 두 번 호출했다. sayHello(3)이라고 호출하면 3이라는 정수형 값이 sayHello(int in) 의 인자 in에 저장된 후 함수가 수행된다. 따라서 “Hello.”라는 문자열이 3번 출력된 것이다. 마찬가지로 두 번째 호출인 sayHello(ia) 는 ia의 값은 5를 이 함수의 인자 in에 전달한다. 그러므로 “Hello.”가 다섯 번 출력 된다.


다른 예로 이번에는 반환값이 있는 함수를 들어보자.


float add(float fa, float fb) {
   float fc = fa + fb;
   return fc;
}


이 함수는 반환값의 자료형이 float형이라고 함수명 앞에 명시되어 있다. 인자(argument)는 두 개이고(fa, fb) 모두 float 형이다. 함수 본체에 보면 변수 fc에 두 인자의 합을 저장한 후 return 명령어를 이용하여 그 값을 반환하고 있다. 따라서 이 함수는 두 실수를 받아서 그 합을 반환하는 함수이다.


이와 같이 반환값이 있는 함수의 경우 호출부에서는 그 반환값을 변수에 저장할 수 있다. 예를 들어 다음과 같다.


float fr;
fr = add(1.0f, 2.5f);//fr에 3.5 저장

float fa = 10.1f, fb = 22.3f;
float fc = add(fa, fb);// fc에 32.3이 저장됨


이와 같이 반환값이 있는 함수의 경우는 호출부에서 그 반환값을 받아서 변수에 저장할 수 있다.


#include <stdio.h>

float add(float fa, float fb) {
   float fc = fa + fb;
   return fc;
}

int main(int argc, char **argv) {
   float fr;
   fr = add(1.0f, 2.5f);
   float fa = 12.3f, fb = 45.6f;
   float fc = add(fa, fb);
   printf("fr = %f, fc = %f", fr, fc);
}


fa = 3.500000, fb = 57.899998


 좀 더 다양한 함수의 정의 예를 다음 표에 들었다.


함수 정의 예

의미

void nop() {... }

반환값이 없음을 명시적으로 나타냄

int sub(int ia, int ib) {...}

두 개의 int형 입력, 반환값도 int형

double round(double dx) {...}

하나의 double형입력, 출력도 double형

void myDate(void) {... }

인자가 없음을 명시적으로 나타냄.

char display(char ca) {...}

하나의 char형입력, 출력도 char형


여기에서는 함수의 기본적인 정의 방법에 대해서 살펴 보았다.


C++ 강좌 전체 목록 >>>


c{c++},n{c0025}

'프로그래밍언어.Lib > C,C++' 카테고리의 다른 글

C++ 의 return 명령어  (0) 2015.05.18
C++ 사용자 함수의 선언  (0) 2015.05.17
C/C++ 함수(function) 개요  (0) 2015.05.17
C++ 클래스 예제 : Led 클래스  (0) 2015.05.17
C++의 생성자와 소멸자 실행 순서  (0) 2015.05.17
Posted by 살레시오
,

7.1 함수의 개요      [gdoc]       [smts]

 C 언어는 구조 지향 언어(structure-oriented language)라고 한다. 이 구조의 핵심으로 함수(function)가 있는데 C 언어는 함수로 시작해서 함수로 끝난다고 해도 과언이 아닐 정도이다. C++언어는 객체 지향(object-oriented) 언어이지만 C언어와의 하위 호환성을 유지하므로 구조 지향적인 프로그래밍도 가능하다.


 C 프로그램은 하나 이상의 함수들로 구성되어 있으며 각 함수들은 다양한 일들을 수행할 수 있는 독립적인(self-containted) 부프로그램을 일컫는다. 전술했듯이 C++ 의 경우 C 언어에 대해서 하위 호환성이 있으므로 함수에 대한 기본적인 내용을 똑같이 적용된다.


 함수는 식별자 뒤에 괄호()가 반드시 붙는다. 괄호가 붙지 않는 식별자는 변수이며 괄호가 붙은 식별자는 함수이다. 맨 처음부터 다뤄온 예제들에서 프로그램 본체인 main() 도 바로 함수이다. 그리고 scanf(), printf() 도 함수이다.


  • main() 함수 : C 프로그램의 시작점

  • scanf(), printf() 함수: 입출력 함수


 특히 C 언어는 함수에 의한 언어라고 할 수 있다. 아무리 덩치가 큰 C 프로그램이라도 모두 함수를 조합하여 만들어진다. 함수의 사전적인 의미는 ‘기능’이다. 즉 ‘어떤 일을 수행하는 프로그램의 작은 단위’를 함수라고 한다.


  • 함수(function) - 어떤 작업을 수행하는 프로그램의 작은 단위


 프로그래밍 입문자는 왜 하나의 프로그램을 여러 개의 함수로 나누어 작성해야 되는지 궁금할 수 있다. 함수를 사용하는 장점으로 다음과 같은 것들을 들 수 있다.


  1. 덩치가 큰 프로그램을 작고 다루기 쉬운 함수(모듈) 단위로 분할해서 설계하고 구현함으로서 프로그램을 더 쉽게 작성할 수 있다.

  2. 프로그램을 단계적으로 개발할 수 있다.

  3. 어떤 프로그램에서 작성한 함수를 다른 프로그램에서 재사용할 수 있다.

  4. 프로그램 내부에 세부적인 연산이나 작업 등을 함수의 내부에 숨길 수 있어 프로그램을 보기에 간결하게 만들 수 있다.


 C 언어의 함수는 이미 만들어져서 사용할 수 있는 표준 함수와 사용자가 만들어 사용하는 사용자 정의 함수로 구분할 수 있다.


  • 표준 함수 (standard function)

  • 사용자 정의 함수 (user-defined function)


지금까지 사용했던 scanf(), printf() 함수는 모두 표준 함수에 속하며 C/C++ 언어 표준에 포함되어 일반 사용자가 가져다 쓸 수 있는 이미 만들어진 함수이다.


 표준 함수와 사용자 정의 함수를 프로그램 내에서 적절하게 활용하면 중복되는 부분을 상당히 줄일 수가 있으며 프로그램의 크기도 줄일 수 있는 효과를 얻을 수 있다. 덩치가 큰 프로그램을 제작할 때 작은 크기의 모듈을 설계하여 전체를 짜 맞추는 식으로 만들어 가면 개발 시간을 단축할 수 있고 프로그램을 보다 명료하게 구현할 수 있다는 장점이 있다.


Posted by 살레시오
,