03:함수

become Xcoder 2011.06.21 23:03
소개
지금까지 본 예제 코드는 가장 긴 것이라도 단 5줄밖에 없었습니다. 몇천줄에 해당하는 프로그램을 짜는것은 아직 머나먼 이후의 일이지만, Objective-C의 특징으로서, 프로그램의 구성의 방법에 대해서 빠른 단계에서 설명하기로 합니다. 
 만약 프로그램이 길고 끊김이 없는 명령의 연속으로 되어 있었다로 하면, 버그를 찾아 수정하는 것은 매우 곤란해집니다. 또, 특정한 동일한 처리가 프로그램내의 복수의 장소로 존재할 경우, 거기에 버그가 있으면, 복수의 버그를 수정하지 않으면 안됩니다. 그런 때, 하나둘은 반드시 못보고 넘기는 것입니다. 그 때문에 코드를 구조화하고, 버그의 수정을 보다간단하게 하는 방법에 대해서 고려해야 합니다. 
 이 문제의 해결 방법으로서, 기능에 따라서 각 명령을 그룹화하는 것을 올릴 수 있습니다. 예를 들면 원의 표면적을 계산하는 명령이 있었다로 합니다. 이 코드가 정확하게 기능하는 것을 한 번 확인하면, 그 이후는 거기에 버그가 있는 것인가 아닌가를 다시 볼 필요는 없습니다. 「함수」라고 불리는 코드의 세트는, 각각 이름을 가지고, 그 이름을 부르는 것으로 함수가 가지는 기능을 사용할 수 있습니다. 이, 함수를 사용한다고 하는 사고방식은 매우 기초적인 것으로, 각프로그램은 적어도 하나는 함수를 가지고 있습니다. main()함수입니다. 컴파일러는 우선 이 main()함수를 발견하고, 여기에서 프로그램의 실행을 시작합니다. 

main()함수
main()함수를 더욱 자세히 보겠습니다.

[1]
main()
{
  // main ()의 본체. 여기에 코드를 쓴다.  
}

[1.1]의 행은 함수의 이름, 즉 main이라고 하는 것이 함수의 이름입니다. 괄호가 이름에 이어집니다. main은 예약어이며, main함수는 각프로그램에 반드시 필요합니다. 만약 자신의 함수를 만들 때는, 그 함수에 자유롭게 이름을 붙일수 (main과 같은 예약어를 제외) 수 있습니다. 괄호에도 의미가 있습니다만, 그것에 대해서는 나중에 설명합니다. 계속해서 행 [1.2, 1.4]에는 안괄호 {}이 있습니다. 함수의 코드는 이 중 괄호 안에 씁니다. 1장으로 사용한 샘플을 다시 봅시다. 
 
[2]
main ()
{
  //이하에 변수의 선언
 float pictureWidth, pictureHeight, pictureSurfaceArea;
 //변수의 초기화(각변수에 적당한 값을 세트)
pictureWidth = 8.0;
pictureHeight = 4.5;
//실제의 계산 처리
pictureSurfaceArea = pictureWidth * pictureHeight;
}

처음의 함수
main()함수에 계속되어 코드를 추가할 경우, 디버그가 보다 어려워져버립니다. 이러한 구조화되지 않고 있는 코드는 피해야 한다고 하는 것은 이미 배웠습니다. 여기에서는 좀더 구조화된 프로그램을 써 봅시다. 프로그램에 필수적인 main()함수와는 달리, circleArea()함수를 만들어 봅니다 [3]. 

[3]
main ()
{
  float pictureWidth, pictureHeight, pictureSurfaceArea;
  pictureWidth = 8.0;
  pictureHeight = 4.5;
  pictureSurfaceArea = pictureWidth * pictureHeight;
}
circleArea() // [3.8]
{
}

간단합니다만, [3.8]로부터 시작되는 함수는 아직 아무런 기능도 없습니다. 함수를 만들 때, main()함수의 밖에 둔다고 하는 것을 우선 기억해 주십시오. 다른 말로 바꿔 말하면, 함수는 네스트(nest= 「상자」와도 번역됩니다) 되지 않습니다. 
 새롭게 만든 circleArea()함수는 main()함수로부터 불립니다. 함수를 부른다 (실행한다)에는 어떻게 하면 좋을가 [4]을 보아 주십시오. 

[4] main ()
{
  float pictureWidth, pictureHeight, pictureSurfaceArea,  circleRadius, circleSurfaceArea;// [4.4]
  pictureWidth = 8.0;pictureHeight = 4.5;
  circleRadius = 5.0;// [4.7]
  pictureSurfaceArea = pictureWidth * pictureHeight;

  // 여기에서 함수의 호출!  
  circleSurfaceArea = circleArea(circleRadius);// [4.11]
}
(프로그램의 나머지의 부분에 관해서는 [3]의 샘플을 보아 주십시오)

인수전달
[4.4]에 새롭게 두개의 float형의 변수를 추가하고, [4.7]에 변수circleRadius를 초기화(값을 대입)했습니다. 가장 중요한 것은 [4.11], circleArea()함수를 읽고 있는 부분입니다. 보아서 아는 대로, 변수circleRadius가 괄호 안에 두어지고 있습니다. 이것은 circleArea ()의 「인수」라고 불립니다. 
circleRadius가 가지는 값이 함수circleArea ()에 받습니다. 그리고, circleArea ()이 실제의 계산 처리를 마치면 함수는 계산 결과를 되돌립니다. [4.11]에서는 함수circleArea ()의 결과를 변수circleSurfaceArea에 대입하고 있습니다. [3]로 본 circleArea()함수를 [5]과 같이 고쳐 써 봅시다 (circleArea()함수만 이하에 싣습니다). 

[5]
circleArea (float theRadius)// [5.1]
{
  float theArea;
  theArea = 3.1416* theRadius * theRadius;//원주율×반경의 자승 [5.4]
  return theArea;
}

[5.1]행에서, circleArea()함수의 입력(인수)로서 float형의 값이 필요한 것을 선언하고 있습니다. 이 입력을 받으면, 그 값을 theRadius라고 하는 이름의 변수에 세트 합니다. 그리고 [5.4]의 계산 결과를 보존해 두기 위한 변수가 필요하므로, main()함수 [4.4]과 같이, [5.3]에서 변수theArea를 선언하고 있습니다. 변수theRadius의 선언은 [5.1]의 괄호 안에서 끝나고 있는 것에 주의해 주십시오. 
[5.5]에서는 계산 결과를, 이 함수를 호출한 원래의 함수에 되돌리고 있습니다 (함수의 결과를 반환값이라고 합니다). 결과로서, [4.11]에 변수circleSurfaceArea에 계산 결과가 세트 됩니다. 
 [5]의 함수의 샘플에는 나중 하나 해야 할 것이 남아있습니다. 함수가 되돌리는 값(반환값)의 데이터의 형을 지정하지 않으면 안됩니다. 컴파일러가 그것을 필요로 하고 있기 때문입니다. 거기에서, [6.1]과 같이 반환값의 형으로서 float를 지정합니다. 

[6]
float circleArea (? oat theRadius)// [6.1]
{
  float theArea;
  theArea = 3.1416* theRadius * theRadius;
  return theArea;
}

[6.1]의 선두의 float는, 함수에 의해 되돌려지는 데이터 (즉 여기에서는 변수theArea의 값)이 float형인 것을 내보이고 있습니다. main()함수 [4.8]에서 circleArea()로부터 되돌아가 값을 받는 변수circleSurfaceArea도 같은 형(역시 float)이다라고 하는 것을, 프로그래머로서 확실히 확인해 주십시오. 그렇게 하면 컴파일러로부터 나중에 불평을 되는 걱정은 없습니다. 
 모든 함수가 인수를 필요로 하고 있는 것이 아닙니다. 만약 인수가 없어도 내용이 없는 괄호 ()는 필요합니다. 

[7]
int throwDice()
{
  int noOfEyes;
  //1로부터 6의 값을 랜덤해서 만드는 코드
  return noOfEyes;
}

반환값
모든 함수가 반환값을 가지는 것이 아닙니다. 함수에 반환값이 없을 경우, void형을 지정합니다. 또 return명령은 있어도 없어도 괜찮습니다. 반환값이 없는 함수로 return을 사용할 경우, return의 뒤에는 변수명이나 값등은 쓰지 않습니다. 

[8]
void beepXTimes(int x)
{
  //비프 소리를 x회 울리는 코드
  return;
}

다음 pictureSurfaceArea ()과 같이 복수의 인수를 잡는 함수의 경우, 각인수는 콤마에서 단락 짓습니다. 

[9]
float pictureSurfaceArea (float theWidth,float theHeight)
{
  //코드
}

main()함수는 int형의 값을 되돌리는 것이라고 결정되어 있습니다. 물론 return이 필요합니다. 기본적으로는 프로그램에 문제가 발생하지 않은 것을 나타내기 위해서, 0을 되돌립니다 [10.9]. main()함수의 리턴값은 int이므로, [10.1]과 같이 main() 앞에 int를 씁니다. 그러면 지금까지의 코드를 모아 봅시다.

[10]
int main ()
{
  float pictureWidth, pictureHeight, pictureSurfaceArea,  circleRadius, circleSurfaceArea;
  pictureWidth = 8;pictureHeight = 4.5;
  circleRadius = 5.0;
  pictureSurfaceArea = pictureWidth * pictureHeight;
  circleSurfaceArea = circleArea(circleRadius);// [10.9]
  return  0;// [10.10]
}
float circleArea (float theRadius)// [10.13]
{
  float theArea;
  theArea = 3.1416* theRadius * theRadius;
  return theArea;
}

마무리 
[10]을 보아서 아는시는 대로, [10.1]에 main()함수가, [10.13]에 스스로 정의한 함수가 있습니다. 만약 이 코드를 컴파일하면, 컴파일러는 아직 잘 컴파일 할 수 없습니다. [10.9]줄로, circleArea()라고 하는 이름의 함수는 모르는 거라고 불평을 합니다. 왜일까요? 정말로 컴파일러는 main()로부터 읽기 시작했을때, 잘 모르는 단어를 우연히 부닥쳤다라고 하는 것인 것 같습니다. 그리고 컴파일러는 여기에서 읽는 것을 그만두고, 당신에게 경고를 냅니다. 컴파일러를 충족시키기 위해서는, main() 앞에 함수의 정의(전문적으로는 「함수 프로토타입 선언」이라고 말합니다)을 추가하면 OK입니다. [11.1]. 특별히 어려운 것은 없습니다. 행의 마지막에 세미콜론을 두는 것이외는 [10.13]줄과 완전히 같습니다. 이것으로, 컴파일러는 함수를 찾아도 놀라서 경고를 내는 것은 없어집니다. 

[11]
float circleArea (float theRadius);// function declaration
int main()
{
  이후 [10]에 같음

이제 프로그램을 실제로 컴파일합니다만, 우선은 몇몇의 나머지의 작업을 처리합시다. 
프로그램을 코딩할 때는, 나중에 코드를 재이용할 수 있도록 주의를 기울입시다. 이 프로그램도 [12]과 같이 rectangleArea()함수를 만들고, main()함수로부터 부르게 변경할 수 있습니다. 만약 함수를 한 번밖에 사용하지 않을 경우라도, 함수에 정리하는 것은 유익한 것입니다. main()함수는 보다 읽기 쉬워져, 디버그할 때도 버그가 어디에 있는 것인가 보다 찾기 쉬워집니다. 아주 긴 명령을 전부 체크할 필요는 없어지고, 안괄호에서 둘러싸진 함수의 내용만을 체크하면 됩니다.
 
[12]
float rectangleArea (float length,float width)
{
  return (length * width);
}

이러한 간단한 함수의 경우, [12.3]과 같이 계산과 결과를 돌려주는 것을 하나로 정리할 수 있습니다. [10.15]에서는 보다 이해하기 쉽게 하기 위해서, 실제로는 불필요한 변수theArea를 정의하고 있습니다. 

 이 장에서 작성한 함수는 하찮은 것입니다만, 함수의 정의(즉 최초의 행)를 변경하지 않는 한, 호출하는 측의 함수에 아무런 영향도 줄 일 없이 함수의 내용을 변경할 수 있는 점은 매우 중요하므로 기억해 두어 주십시오. 
 예를 들면 함수내의 변수의 이름을 자유로 변경할 수 있고,또 변경해도 정확하게 동작하고, 다른 코드에 영향을 주기도 않습니다. 누군가가 작성한 함수를, 안에서 무엇을 하고 있는 것일지를 몰라도 사용할 수도 있습니다. 그 때 알아둬야 할 것은 함수를 어떻게 해서 사용하면 좋을가, 즉 :

 ·함수의 이름
 ·함수가 취하는 인수의 수, 순번, 데이터의 형
 ·반환값으로서 어떠한 데이터를 반환하는가 ,및 데이터의 형

샘플[12]의 경우에는
 ·rectangleArea
 ·인수는 둘, 최초의 인수가 세로폭, 다음이 가로 폭, 형은 어느쪽도 float
 ·함수는 어떠한 반환값을 반환하고, 그 형은 float ([12.1]의 행으로부터 압니다)

변수의 보호
함수내부의 코드는 main()함수나 기타의 함수로부터 분리되고 있습니다. 그러므로 어떤 함수의 내부의 변수의 값은, 가령 다른 함수내부에서 같은 이름의 변수를 사용하고 있어도, 통상은 그 변경의 영향을 받을 것은 없습니다. 
 이것은 Objective-C의 가장 중요한 기능입니다. 5장에서 이 기능에 대해서 다시 설명합니다. 그러나 그 전에, 샘플 [11]을 Xcode에서 움직여 봅시다. 

원문 http://www.cocoalab.com/?q=node/9 

'become Xcoder' 카테고리의 다른 글

05:프로그램을 컴파일해서 실행  (0) 2011.06.21
04:화면에 표시하기  (0) 2011.06.21
03:함수  (0) 2011.06.21
02:노 코멘트(no comment)? 그것은 안됨!  (0) 2011.06.21
01:프로그램은 인스트럭션의 연속  (0) 2011.06.21
00:시작하기 앞에  (0) 2011.06.21
Posted by tklee