440 likes | 449 Views
Learn about functions in programming, including examples, the structure of a function, why they are needed, and how to use them. Decompose programs, repeat tasks, and make code more manageable with functions.
E N D
清明 ~ 杜牧 清明時節雨紛紛, 路上行人欲斷魂。 借問酒家何處有? 牧童遙指杏花村。
Examples of Functions • y = f(x) = 2 x3 -3 x2 -3 x + 2 • f(x) = sin(x) / cos(x) • g(x) = sin(x) / x
Why Do You Need Functions • A function is a self-contained block of code with a specific purpose. • Sometimes you have to repeat the same task several times in a program. • With functions, you don’t need to replicate the same code at various points. • Decompose a large program into smaller functions makes it easily manageable for development and testing. • A typical program will consist of a large number of small functions, rather than a small number of large functions.
Decompose A Program int main() { show_title(); show_intro(); input(); process(); output(); return 0; } ============ HW1: Sorting ============ This program will require the user to input 10 integers and sort them in ascending order. ============ Now getting 10 integers from the user. ============ Exchange Sort ... ============ Print out the sorted sequence.
Example of Repeated Tasks (1) #include <iostream> using std::endl; using std::cout; int main() { for (int j=1; j<=5; j++) { for (int i=0; i<j; i++) cout << '*'; cout << endl; } for (int j=5; j>=1; j--) { for (int i=0; i<j; i++) cout << '*'; cout << endl; } return 0; } * ** *** **** ***** ***** **** *** ** *
Example of Repeated Tasks (2) #include <iostream> using std::endl; using std::cout; int print_stars(int n) { for (int i=0; i<n; i++) cout << '*'; cout << endl; return 0; } int main() { for (int j=1; j<=5; j++) print_stars(j); return 0; } * ** *** **** *****
Example of Repeated Tasks (3) #include <iostream> using std::endl; using std::cout; int print_stars(int n) { for (int i=0; i<n; i++) cout << '*'; cout << endl; return 0; } int main() { for (int j=1; j<=5; j++) print_stars(j); for (int j=5; j>=1; j--) print_stars(j); return 0; } * ** *** **** ***** ***** **** *** ** *
Structure of a Function // Function to calculate x to the power n double power(double x, int n) { double result = 1.0; for (int i = 1; i<=n; i++) result *= x; return result; } Function Header Function Body
The Function Header double power ( double x, int n ) • The name of a function is governed by the same rules as those for a variable. • A function returns either a single value, or nothing at all (void). • The single value returned can be a pointer, which contains the address of an array. type of the return value function name parameters
{ double result = 1.0; for (int i = 1; i<=n; i++) result *= x; return result; } The return Statement Return a value (evaluated from an expression) to be the functional value. If the type of return value of this function is declared as void, there must be no expression. return; The Function Body
Define the function before it is called. However, many programmers prefer to see main() earlier to have a global view. Declare the function using a statement called a function prototype. void print_stars() { cout << "*********" << endl; } int main() { print_stars(); cout << "Test" << endl; print_stars(); } Using a Function
Define Your Function Based on Existing Functions // 四捨五入 #include <iostream> #include <cmath> int round(float x) { return floor(x + 0.5); } void print(int n) { std::cout << n << std::endl; return; } int main() { print( round(4.4) ); print( round(4.5) ); return 0; }
Function Prototypes (P.184) • It contains the same information as appears in the function header, with the addition of a semicolon (;). • double power(double value, int index); • void print_stars(); • You can even omit the names of the parameters • double power(double, int); • However, it is better to use meaningful name in a prototype to increase readability.
Example of Using Function Prototypes void print_stars(); int main() { print_stars(); cout << "Test" << endl; print_stars(); } void print_stars() { cout << "*********" << endl; }
Using a Function • Ex5_01.cpp on P.185 • Note the 3 ways to call this function: • Passing constants as arguments • power(5.0, 3) • Passing expressions (variables) as arguments • power(3.0, index) • Using a function as an argument • power(x, power(2.0, 2.0))
You May Separate Your Code into Several Files CC test.cpp stars.cpp -o test.exe #include <iostream> using std::cout; void print_stars(); // function prototype int main() { cout << "Good morning.\n"; print_stars(); cout << "Good afternoon.\n"; } #include <iostream> void print_stars() { std::cout << "******\n"; } test.cpp stars.cpp
Define function prototypes in a header file #include <iostream> using std::cout; #include "stars.h" int main() { cout << "Good morning.\n"; print_stars(); cout << "Good afternoon.\n"; } void print_stars(); stars.h test.cpp Compile with the same command: g++ test.cpp stars.cpp -o test.exe
Passing Arguments to a Function • There are two mechanisms in C++ to pass arguments to functions • Pass-by-value • Pass-by-reference
Pass-by-value • Copied of arguments are stored in a temporary location in memory. • This mechanism protect your caller arguments from being accidentally modified by a rogue function.
A function may modify the parameters void stars(int n) { while (n > 0) { cout << '*'; --n; } cout << endl; } int main() { int i = 5; stars(i); cout << i << endl; }
Ex5_02.cpp on P.190 int main(void) { int num = 3; cout << endl << "incr10(num) = " << incr10(num) << endl << "num = " << num; cout << endl; return 0; } int incr10(int n) { n += 10; cout << "In the function, n = " << n << endl; return n; } copy num 3 3 n 13 Replace “num” with “n” in incr10(). This may makes Ex5_02.cpp more clear.
Exercise: ch5-box.cpp • Design a functionvoid box(int n)to draw a box, which has n stars on each edge.
Exercise: bool isDigit(char c) • Design a functionbool isDigit(char c)which returns true when c is a decimal digit character ‘0’, ‘1’, ‘2’, …, ‘9’. • You may test your function with the following main program: int main() { char str[] = "1A2B.g0v"; for (int i=0; i< strlen(str); i++) if ( isDigit(str[i]) ) cout << "True" << endl; else cout << "False" << endl; return 0; }
Pointers as Arguments to a Function • Ex5_03.cpp on P.191 • int incr10(int *num); // Function Prototype • int* pnum = # // Pointer to num • *num += 10; • return *num; • // de-reference the pointer to get the return value • // Replacing “num” with “p” in incr10() may make it more clear.
Ex5_02.cpp vs. Ex5_03.cpp copy num 3 num 3 13 3 3 n 13 p 0012FF6C de-reference n += 10 *p += 10
Passing Arrays • The pointer to the beginning of the array is passed by value to the function. • Ex5_04.cpp on P.192 • double average(double array[], int count); • average(values, (sizeof values)/(sizeof values[0])); • sizeof values = ? • sizeof values[0] =? • card_shuffle.cpp
Exercise: Passing a String • Design a function show_name_box(char* s) which takes a string as the parameter, and print a line of equal signs (‘=‘) before and after it. • Test your program with the main program: int main() { char* name[] = { "Alice", "Bob", "Charlie", "Dvorak" }; int i; for (i=0; i < sizeof(name) / sizeof(name[0]); i++) show_name_box(name[i]); return 0; } • The result may look like ===== Alice ===== === Bob === ======= Charlie ======= ====== Dvorak ======
Exercise • P.217 Ex.2 • Write a function that swaps two integers, using pointers as arguments. • Write a program that uses this function and test that it works correctly. int main() { int i, j; cout << "Input two integers -- "; cin >> i >> j; cout << i << j << endl; swap(&i, &j); cout << i << j << endl; return 0; }
Exercise: Conversion to Lowercase • Design a functionvoid ToLower(char* s)which will convert the characters in the input argument from uppercase to lowercase. • Test your function with the following main program: int main() { char buffer[80]; cout << "Please input a word -- "; cin >> buffer; ToLower(buffer); cout << buffer << endl; return 0; }
What Is a Reference? • A reference is an alias for another variable(Chapter 4, P.168). • long number = 0; • long& rnumber = number; • rnumber += 10; • cout << number; • Difference between a pointer and a reference: • A pointer needs to be de-referenced • A reference is an alias. There is no need for de-referencing.
Pass-by-reference • Remember that a reference is merely an alias. • Ex5_07.cpp on P.197 • The output shows that the function incr10() is directly modifying the variable passed. • This mechanism allows a function to modify the value of an argument in main(), just like the pointer in Ex5_03.cpp (P.191). • However, passing by reference makes the program look for elegant.
A function can modify the parameters void stars(int&n) { while (n > 0) { cout << '*'; --n; } cout << endl; } int main() { int i = 5; stars(i); cout << i << endl; }
Static Variables in a Function (P.212) • With only “automatic” variables within a function, you can’t count how many times a function is called. • Within a function, you can declare a variable as static so that its value persists from one call to the next. • Initialization of a static variable within a function only occurs the first time that the function is called. • Ex5_14.cpp on P.213
Recursive Function Calls (P.214) • Recursive function - A function calls itself • Either directly or indirectly • fun1 fun2 fun1 • Fibonacci sequence: • F(n) = F(n-1) + F(n-2) • F(0) = 0, F(1) = 1 • Factorial • N! = N*(N-1)*(N-2)*…*3*2*1 • F(n) = n * F(n-1) • F(0) = 1 • Be sure to specify the boundary condition to stop the recursive call!
Fibonacci Sequence • Implemented as a recursive function // ch5_fibonacci.cpp #include <iostream> using std::cout; using std::endl; int f(int n) { if (n == 0) return 0; if (n == 1) return 1; return f(n-1) + f(n-2); // recursive call } int main() { for (int i=0; i<20; i++) cout << f(i) << ' '; cout << endl; return 0; } Compare with the one implemented as an array
Factorial (P.217 Ex.1) // factorial.cpp #include <iostream> using std::cout; using std::endl; int f(int n) { if (n <= 0) return 1; else return f(n-1)*n; } int main() { for (int i=1; i<=10; i++) cout << i << "! = "; cout << f(i) << endl; return 0; } 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 6! = 720 7! = 5040 8! = 40320 9! = 362880 10! = 3628800
Decimal → Octal • 2310→ 278 • 8810→ 1308 • 12810→ 2008 88 % 8 oct(88 / 8)
ch5_dec2oct.cpp #include <iostream> using std::cout; using std::endl; void oct(int n) { if (n >= 8) oct( n / 8); // recursive call cout << n % 8; } int main() { oct(23); cout << endl; oct(88); cout << endl; oct(128); cout << endl; return 0; } 27 130 200
Exercise • Convert decimal to hexadecimal by a recursive function. • You may test your function with the following main program. int main() { hex(23); cout << endl; hex(88); cout << endl; hex(127); cout << endl; hex(128); cout << endl; hex(255); cout << endl; hex(256); cout << endl; return 0; }