Download
slide1 n.
Skip this Video
Loading SlideShow in 5 Seconds..
Function PowerPoint Presentation

Function

82 Views Download Presentation
Download Presentation

Function

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

  1. Function Prof. Jung Guk Kim HUFS, jgkim@hufs.ac.kr

  2. 목표 • 함수와 프로시저를 프로그램하기 • 인자 전달 개념에 친숙하기 • 값 인자와 참조 인자를 언제 사용하는지를 알기 • 함수 주석의 중요성을 알기 • 변수 범위를 결정 • 부대효과와 전역 변수의 사용을 최소화 • 복잡한 작업을 보다 단순한 작업들로 나누는 전략을 개발 • 함수와 사전 조건이 있는 함수 호출자의 책임을 문서화하기 2

  3. 블랙박스로서의 함수(1) • 함수(function)는 이름을 가진 코드이다. • sqrt() – 부동소수점 수의 제곱근 계산 • getline() – 스트림으로부터 한 줄 읽기 • 함수는 블랙박스– 함수 사용 시 함수 내부 코드를 알 필요가 없다. • 다른 함수가 실행 중일 때 main() 함수의 실행은 잠시 중단된다. 3

  4. 블랙박스로서의 함수(2) • 함수는 함수로 전달될 입력 값을 인자로 받는다. • x는 인자: y = sqrt(x); • x와 y는 인자: z = pow(x, y); • 수식은 인자: sqrt(b * b - 4 * a * c); • 함수는 출력 즉 반환 값을 가진다. • y 는 반환 값을 저장: y = sqrt(x); • 인자와 반환 값을 데이터 타입을 가진다. • 오류: sqrt("Harry"); • 오류: string s = sqrt(5.5); 4

  5. 함수 작성(1) 5

  6. 함수 작성(2) • 함수 이름, 반환 값 타입, 인자 • double future_value(double p) • 함수 실행 동안 인자는 인자 변수( parameter variable)에 저장된다.(예, p). • 함수 몸체는(body)는 중괄호로 구분된다: double future_value(double p) { . . . } • 반환 값은 호출한 함수로 반환된다. double future_value(double p) {     double b = 1000 * pow(1 + p / 100, 10);     return b; } 6

  7. 함수 작성(futval.cpp) 7

  8. 함수 작성(Hard Wired Values : 함수 내부에 주어진 값) • 위의 future_value함수의 단점: 초기 투자액과 년수가 hard-wired 되어있다 • Hard-wiring는 함수의 재사용을 어렵게 한다: • 20년 후의 투자액은?. • 이자율이 달라진다면?. • hard-wired values를 함수에 인자로 전달하면 함수가 재사용 가능해진다. • 재사용 가능하도록 함수를 설계하는 것이 좋다. double future_value(double initial_balance, double p, int n) { double b = initial_balance * pow(1 + p / 100, n); return b; } 8

  9. 함수 주석(1) • 모든 함수에 주석을 붙여야 한다. • 주석은 프로그램을 읽는 사람에게 도움을 준다. • 주석을 쓰는데 표준적인 방법은 없지만, 이 책은 javadoc스타일 사용 • @param 은 각 인자 설명 • @return 은 반환 값 설명 • 코드를 작성하기 전에 먼저 주석을 달 것! 9

  10. 함수 주석(2) /** Computes the value of an investment with compound interest. @param intial_balance the initial value of the investment @param p the interest rate pre period in percent @param n the number of periods the investment is held @return the balance after n periods */ double future_value(double initial_balance, double p, int n) { double b = initial_balance * pow(1 + p / 100, n); return b; } 10

  11. 반환 값(1) Syntax 5.2 : return Statement 11

  12. 반환 값(2) • return 문이 실행되면 함수를 빠져 나간다. double future_value(double initial_balance, double p, int n) { if (n < 0) return 0; if (p < 0) return 0; double b = initial_balance * pow(1 + p / 100, n); return b; } 12

  13. 반환 값(3) • 함수의 실행이 끝날 때에는 언제나 반환 값을 가진다. double future_value(double initial_balance, double p, int n) { if (p >= 0) return = initial_balance * pow(1 + p / 100, n); /* Error */ } 13

  14. 반환 값(4) • true/false 값을 반환하는 함수를 술어(predicate) 함수라 한다. bool approx_equal(double x, double y) { const double EPSILON = 1E-14; if (x == 0) return fabs(y) <= EPSILON; if (y == 0) return fabs(x) <= EPSILON; return fabs(x - y) / max(fabs(x), fabs(y)) <= EPSILON; } 14

  15. 반환 값 approx.cpp(5) 15

  16. 반환 값 approx.cpp (6) 16

  17. 인자 (1) • 함수 호출에 수식을 사용 가능 • b = future_value(total / 2, rate, year2 - year1); • 인자 변수는 변수처럼 수정 가능하다. double future_value(double initial_balance, double p, int n) { p = 1 + p / 100; double b = initial_balance * pow(p, n); return b; } • 인자 변수의 수정은 나쁜 스타일이다 17

  18. 인자(2) 18

  19. 부대효과(Side Effects) • 함수 실행으로 외부에서 관찰 가능한 효과(side effect) • 스크린 디스플레이(오류 메세지를 포함해서). • 함수 밖에 있는 변수의 수정. • 프로그램의 실행을 종료. • 값을 반환하는 것을 제외하고는 함수 외부에 영향을 주어서는 안된다. • 함수에서 값 출력의 문제점. • 그래픽스 프로그램은 출력 스트림이 없다. • 이상적인 함수는 부대작용없이 하나의 값을 계산하는 함수 19

  20. 프로시저(1) • 반환 값이 없는 함수. • print_time(now); • 반환 값이 없음을 나타내는 키워드: void. void print_time(Time t) { cout << t.get_hours() << ":";    if (t.get_minutes() < 10) cout << "0";             cout << t.get_minutes() << ":“;    if (t.get_seconds() < 10) cout << "0";                 cout << t.get_seconds(); } • 프로시저는 반환 값이 없으므로 부대작용이 있어야 한다. • 이상적인 프로시저: 하나의 부대작용만 포함 20

  21. 프로시저(2) 21

  22. 프로시저(3) 22

  23. 참조인자 (Reference Parameters(1)) • 지금까지의 인자를 모두 값 인자(value parameters)라 부른다. • 값 인자의 수정은 원래 값에 영향을 주지 않는다. • 참조 인자는 새로운 변수를 만들지 않고, 기존 변수를 참조한다. • 참조 인자를 변환하면 참조인자가 참조하는 변수의 값이 변경된다. 23

  24. 참조인자 (2) • 참조 인자는‘&’를 사용하여 표시. void raise_salary(Employee& e, double by) {   double new_salary = e.get_salary() * ( 1 + by / 100);    e.set_salary(new_salary); } 24

  25. 참조인자(3) 25

  26. 참조인자(4) 26

  27. 참조인자(5) 27

  28. 변수범위(Variable Scope(1)) • 다른 함수에 같은 이름을 가진 변수를 사용할 수 있다. • 프로그램에서 변수가 보이는 부분을 변수 범위라 부른다. • 변수 범위는 변수가 정의된 부분부터 변수가 정의된 블록 끝까지이다. 28

  29. An Example : Variable Scope(2) double future_value(double initial_balance, double p, int n) {        double r = intial_balance * pow(1 + p / 100, n); return r; } int main()        {     cout << "Please enter the interest rate in percent: “;     double r;     cin >> r;    double balance = future_value(10000, r, 10);     cout << "After 10 years the balance is" << balance          << "\n";      return 0; } 29

  30. 전역 변수(1) • 함수 밖에 정의된 변수 • 전역 변수는 모든 함수에서 볼 수 있다. • 전역 변수의 사용을 최소화해야 한다. • 전역 변수의 사용이 불가피한 경우(cin, cout, and cwin) 30

  31. An Example : Global Variables(2) 31

  32. 단계별 세분화(Stepwise Refinement) • 문제 해결을 위한 좋은 방법 • 복잡한 문제를 풀 경우, 더 단순한 작업으로 나누어서 생각하라. • How do you get coffee? • Ask someone else to do it. • Make coffee. • OK, how do you make coffee? • Make instant coffee. • Brew Coffee. • How do you make instant coffee? • Start by boiling water. • Etc. 32

  33. 유사코드(Pseudocode)로부터 코딩(1) • 프로그램 코딩 전에 계획을 세우라. • 한 곳 이상에서 필요한 코드라면 함수를 작성한다. • 전체 함수를 작성하기 전에 먼저 주석을 단다. • Example: Writing the function /**   Turns a number into its English name.   @param n a positive integer < 1,000,000   @return the name of n (e.g. "two hundred seventy four"·    */ string int_name(int n); 33

  34. 유사코드(Pseudocode)로부터 코딩(2) • 문제를 더 작은 단위로 분리하라 /** Turns a digit into its English name @param n an integer between 1 and 9 @return the name of n ("one" ... "nine") */ string digit_name(int n); /** Turns a number between 10 and 19 into its English name. @param n an integer between 10 and 19 @return the name of n ("ten"..."nineteen") */ string teen_name(int n); /** Gives the English name of a multiple of 10 @param n an integer between 2 and 9 @return the name of 10 * n ("twenty"..."ninety") */ string tens_name(int n); • 빠진 부분은? • 백단위에 대해서는? • 천 단위에 대해서는? 34

  35. 유사코드(Pseudocode)로부터 코딩(3) • 알고리즘이 복잡하면 유사코드(pseudocode)를 작성해 본다. • 유사 코드는C++와 자연어의 중간 정도의 표현이다. string int_name(int n) { int c = n; /* the part that needs to be converted */ string r; /* the return value */ if (c >= 1000) { r = name of thousands in c + "thousand" remove thousands from c } if (c >= 100) { r = r + name of hundreds in c + "hundreds" remove hundreds from c } 35

  36. 유사코드(Pseudocode)로부터 코딩(4) if (c >= 20) { r = r + name of tens in c remove tens from c } if (c >= 10) { r = r + name of c c = 0 } if (c > 0) r = r + name of c; return r; } 36

  37. 유사코드(Pseudocode)로부터 코딩(5) #include <iostream> #include <string> using namespace std; /**    Turn a digit into its English name    @param n an integer between 1 and 9    @return the name of n ("one" . . . "nine") */ string digit_name(int n) {     if (n == 1) return "one";    if (n == 2) return "two";    if (n == 3) return "three";    if (n == 4) return "four";    if (n == 5) return "five";    if (n == 6) return "six";    if (n == 7) return "seven";    if (n == 8) return "eight";    if (n == 9) return "nine";    return ""; } 37

  38. 유사코드(Pseudocode)로부터 코딩(6) /**    Turn a number between 10 and 19 into its English name    @param n an integer between 10 and 19    @return the name of n ("ten" . . . "nineteen") */ string teen_name(int n) {     if (n == 10) return "ten";    if (n == 11) return "eleven";    if (n == 12) return "twelve";    if (n == 13) return "thirteen";    if (n == 14) return "fourteen";    if (n == 15) return "fifteen";    if (n == 16) return "sixteen";    if (n == 17) return "seventeen";    if (n == 18) return "eighteen";    if (n == 19) return "nineteen";    return ""; } 38

  39. 유사코드(Pseudocode)로부터 코딩(7) /**    Give the English name of a multiple of 10    @param n an integer between 2 and 9    @return the name of 10 * n ("twenty" . . . "ninety") */ string tens_name(int n) {     if (n == 2) return "twenty";    if (n == 3) return "thirty";    if (n == 4) return "forty";    if (n == 5) return "fifty";    if (n == 6) return "sixty";    if (n == 7) return "seventy";    if (n == 8) return "eighty";    if (n == 9) return "ninety";    return ""; } 39

  40. 유사코드(Pseudocode)로부터 코딩(8) /**    Turn a number into its English name    @param n a positive integer < 1,000,000    @return the name of n (e.g. "two hundred seventy four") */ string int_name(int n) {  int c = n; /* the part that still needs to be converted */    string r; /* the return value */    if (c >= 1000)    {        r = int_name(c / 1000) + " thousand";       c = c % 1000;    }    if (c >= 100)    {        r = r + " " + digit_name(c / 100) + " hundred";       c = c % 100;    }    if (c >= 20)    {        r = r + " " + tens_name(c / 10);       c = c % 10;    } 40

  41. 유사코드(Pseudocode)로부터 코딩(9)   if (c >= 10)    {        r = r + " " + teen_name(c);       c = 0;    }    if (c > 0)       r = r + " " + digit_name(c);    return r; } int main() {     int n;    cout << "Please enter a positive integer: ";    cin >> n;    cout << int_name(n);    return 0; } 41

  42. 유사코드(Pseudocode)로부터 코딩(10) • 유사 코드는 자연어 설명보다 읽기 쉽다. • 상세한 부분은 생략할 수 있다. • int_name 함수는 자신을 호출한다 (재귀 함수): if (c >= 1000) { r = int_name(c / 1000) + " thousand"; c = c % 1000; } 42

  43. int_name (n = 416) int_name (n = 416) c c r r 416 416 “” “” 검토 Walkthroughs(1) • 손으로 따라가며 확인하기 • 함수 이름과 변수를 가진 테이블을 이용하여 값을 추적한다. • 함수가 다른 함수를 호출하는 경우 테이블 추가 digit_name (n=4) Return “four” 43

  44. 검토 Walkthroughs(2) 44

  45. 사전 조건Preconditions(1) • 부적절한 값으로 함수가 호출된다면(e.g. sqrt(-1))? • 함수의 실패. (digit_name 는 부적절한 값으로 호출되면 빈 스트링을 반환한다). • 함수의 종료(cmath library의 함수들) • 오류 메세지를 보내고 프로그램을 종료하는 것은 좋은 방법이 아니다. • C++ 에는 예외(exception)라는 좋은 방법이 있다. 45

  46. 사전 조건Preconditions(2) 46

  47. 사전 조건 Preconditions(3) • assert() 사용시#include<cassert> 포함할 것 double future_value(double initial_balance, double p, int n) { assert(p >= 0); assert(n >= 0); return initial_balance * pow(1 + p / 100, n); } 47

  48. Preconditions(4) • 프로그래머는 사전 조건에 대한 주석을 달아야 한다. /** Computes the value of an investment with compound interest. @param initial_balance the initial value of the investment @param p the interest rate in percent; must be >= 0 @param n the number of periods the investment is held; must be >= 0 @return the balance after n periods */ 48