函數
2
本章主題
 函數的定義與宣告
 變數的能見度
 參數的傳遞
 內嵌(inline)函數
 遞迴函數(Recursive Function)
 主程式的引數
 函數的應用
3
1 函數的定義與宣告
 定義函數的語法】
 函數型態 函數名稱(資料型態 參數1,資料型態 參數2, …)
 {
 // 函數主體
 [return expression ;]
 }
 函數型態
 函數名稱
 參數列
 函數主體
4
函數的定義與宣告
 【呼叫函數的語法】
 函數名稱(引數1,引數2, …);
 函數的宣告--函數原型
 函數型態 函數名稱(資料型態 參數1,資料型態 參數2, …);
int main()
{
...
i = max(a,b) ;
...
}
int max(int x,int y)
{
if (x > y)
return x ;
else
return y ;
}
呼叫函數
返回
5
函數範例
6
1. // 程式功能: 計算 n!
2. #include <stdio.h>
3. long factorial(int n); //宣告factorial函數
4. int main()
5. {
6. int n = 1;
7. printf("請輸入正整數n:");
8. scanf("%d", &n);
9. printf("n");
10. printf("n!=%d" ,factorial(n)); //呼叫factorial函數
11. return 0;
12. }
13. long factorial(int n) //定義factorial函數
14. {
15. long factorial = 1;
16. while(n > 1)
17. factorial *= n--;
18. return factorial;
19. }
7
2 C的程式架構
 #include < >
 #define
 資料型態 函數1(參數列); // 函數原型,即函數的宣告
 資料型態 函數2(參數列); // 函數原型,即函數的宣告
 ...
 全域變數的宣告;
 資料型態 main(參數列) // 定義main函數
 {
 私有變數的宣告;
 函數主體;
 return 運算式或值;
 }
 資料型態 函數1(參數列) // 定義函數1
 {
 私有變數的宣告;
 函數主體;
 return 運算式或值;
 }
 資料型態 函數2(參數列) // 定義函數2
 {
 私有變數的宣告;
 函數主體;
 return 運算式或值;
 }
8
3 變數的能見度(存活空間)
 全域(Global)變數
 全域變數可以在整個程式中使用
 私有(Private)變數
 從宣告處開始,到該函式結束為止
 { }
 靜態 (Static) 變數
 從宣告處開始,到該函式結束為止
 函式結束時,該變數會被保留再記憶體裡,下次執行該函式
時,該變數不會被重新設定,而以前一次保留下來的值運作。
 範疇運算子(::)
 若在函數內想使用全域變數可使用範疇運算子
 ::
9
1. // 程式功能: 測試全域變數及私有變數
2. #include <stdio.h>
3. void func1(void);
4. void func2(void);
5. int i = 1000; // i為全域變數
6. void main(void)
7. {
8. int i = 0, j = 0 , k = 0; // i,j,k為main( )的私有變數
9. printf("main().i = %d" ,i);
10. printf(",main().j = %d" ,j);
11. printf(",main().k = %dn" ,k);
12. func1() ; // 呼叫func1( ),不傳遞引數
13. printf("main().i = %d" ,i);
14. printf(",main().j = %d" ,j);
15. printf(",main().k = %dn" ,k);
16. return;
17. }
10
1. void func1(void)
2. {
3. int i = 88, j = 88; // i,j為func1( )的私有變數
4. printf(" 【進入func1】n");
5. printf(" func1().i = %d" ,i);
6. printf(",func1().j = %dn" ,j);
7. func2(); // 呼叫func2( ),不傳遞引數
8. func2();
9. printf(" func1().i = %d" ,i);
10. printf(",func1().j = %dn" ,j);
11. printf(" 【離開func1】n");
12. return;
13. }
14. void func2(void)
15. {
16. int j = 999; // j為func2( )的私有變數
17. static int k = 999; // k為func2( )的靜態私有變數
18. printf(" 【進入func2】n");
19. printf(" func2().i = %d" ,i);
20. printf(",func2().j = %d" ,j);
21. printf(",func2().k = %dn" ,k);
22. printf(" 【離開func2】n");
23. i++;
24. j++;
25. k++;
26. return;
27. }
接續上一頁
11
 // 程式功能: 全域變數的使用
1. #include <stdio.h>
2. int i = 1000; // i為全域變數
3. void main(void)
4. {
5. int i = 0; // i 為main( )的私有變數
6.
7. printf("私有.i = %dn", i);
8. printf("全域.i = %dn", ::i);
9.
10. return;
11. }
12
4 參數的傳遞
 以值傳遞(Call By Value)
 以址傳遞(Call By Address)
 以參考值傳遞(Call By Reference)
13
以值傳遞(Call By Value)
 int i = 789, j = 876 ,r;
 r = add(80, 90);
 printf("add(80,90) = %dn", r);
 printf("add(%d,%d) = %dn", i, j, add(i,j));
int add(int x, int y)
{
x += y;
return x;
}
【執行結果】
add(80,90) = 170
add(789,876) = 1665
 參數傳遞時會產生一副本,將副本
傳給函數,函數中數值改變不會影
響原本的變數值
14
1. // 程式功能: 測試以值傳遞
 #include <stdio.h>
 #include <conio.h>
 #include <cstdio>
 #include <string>
 using namespace std;
 int add(int, int); // 函數原型也可以如此寫
 string add(string, string);
 void main(void)
 {
 int i = 789, j = 876 ,r;
 string x = "object";
 string y = "oriented";
 r = add(80,90) ;
 printf("add(80,90) = %dn", r);
 printf("add(%d,%d) = %dn", i, j, add(i,j));
 printf("add(%s,%s) = %sn", x.c_str(), y.c_str(), add(x, y).c_str());
 _getch(); return;
 }
 int add(int x, int y)
 {
 x += y;
 return x;
 }
 string add(string x, string y)
 {
 x += (" " + y);
 return x;
 }
15
以址傳遞(Call By Address)
1. int i = 789, j = 876;
2. printf("i=%dn", i);
3. printf("j=%dn", j);
4. printf("i+j=%dn", add(&i, &j));
5. printf("i=%dn", i);
6. printf("j=%dnn", j);
int add(int *x, int *y)
{
*x += *y;
*y = -(*y);
return *x;
}
【執行結果】
i = 789
j = 876
i + j = 1665
i = 1665
j = -876
 參數傳遞時將引數傳遞給函數參數,
函數執行完畢後在將參數值傳回給
呼叫者。數值改變會影響原本的變
數值
16
1. // 程式功能: 測試以址傳遞--以整數及字串為例
 #include <stdio.h>
 #include <conio.h>
 #include <cstdio>
 #include <string>
 using namespace std;
 int add(int*, int*); // 函數原型
 string add(string*, string*); // 函數原型
 void main(void)
 {
 int i = 789, j = 876;
 string x = "object";
 string y = "oriented";
 printf("i = %dn",i);
 printf("j = %dn",j);
 printf("i + j = %dn", add(&i, &j)); // 以址傳遞
 printf("i = %dn",i);
 printf("j = %dnn",j);
 printf("x = %sn", x.c_str());
 printf("y = %sn", y.c_str());
 printf("x + y = %sn", add(&x, &y).c_str()); // 以址傳遞
 printf("x = %sn", x.c_str());
 printf("y = %snn", y.c_str());
 printf("n按<<Enter>>結束程式."); _getch(); return;
 }
17
接續上一頁
 int add(int *x, int *y)
 {
 *x += *y;
 *y = -(*y);

 return *x;
 }
 string add(string *x, string *y)
 {
 *x += (" " + *y);
 *y = "change";

 return *x;
 }
18
1. // 程式功能: 測試以址傳遞--以陣列為例
2. #include <stdio.h>
3. #include <iomanip>
4. #include <cstdio>
5. using namespace std;
6. void printf_score(string s, int a[], int len); // 函數原型
7. void add_score1(int *a, int len); // 函數原型,以指標為參數
8. void add_score2(int a[], int len); // 函數原型,以陣列為參數
9. void main(void)
10. {
11. int len = 0;
12. int score[] = {85,73,67,90,81,78,90,66,88,78};
13. len = sizeof(score)/sizeof(score[0]); // 取得陣列元素個數
14. printf_score("呼叫前: ", score, len);
15. add_score1(score,len); // 傳遞陣列
16. printf_score("呼叫後: ", score, len);
17. printf("n");
18. printf_score("呼叫前: ", score, len);
19. add_score2(score,len); // 傳遞陣列
20. printf_score("呼叫後: ", score, len);
21. return;
22. }
19
23. void add_score1(int *a, int len) // 每人加5 分
24. {
25. int i = 0;
26. for(i = 0 ; i < len ; i++){
27. *a++ += 5;
28. }
29. return;
30. }
31. void add_score2(int a[], int len) // 將全班最高分調到分,其餘遞增
32. {
33. int i = 0, j = 0, max = 0;
34. for(i = 0; i < len; i++){
35. max = (a[i] > max) ? a[i] : max; // 單行條件式
36. }
37. j = 100 - max;
38. for(i = 0 ;i < len; i++){
39. a[i] += j;
40. }
41. return ;
42. }
43. void printf_score(string s, int a[], int len) // 印出全班成績
44. {
45. printf("%s",s.c_str());
46. for(int i = 0; i < len; i++){
47. printf("%5d",a[i]);
48. }
49. printf("n");
50. }
接續上一頁
20
以參考值傳遞(Call By Reference)
 int i = 789, j = 876;

 printf("i=%dn",i);
 printf("j=%dn",j);
 printf("i+j=%dn",add(i,j));
 printf("i=%dn",i);
 printf("j=%dnn",j);
int add(int &x, int &y)
{
x += y;
y = -(y);
return x;
}【執行結果】
i = 789
j = 876
i + j = 1665
i = 1665
j = -876
 將函數參數視為引數的別名,函數
中數值改變會影響原本的變數值
21
1. // 程式功能: 測試以參考值傳遞
 #include <stdio.h>
 int add(int &x, int &y); // 函數原型
 void main(void)
 {
 int i = 789, j = 876;

 printf("i = %dn",i);
 printf("j = %dn",j);
 printf("i + j = %dn",add(i,j));
 printf("i = %dn",i);
 printf("j = %dnn",j);
 return;
 }
 int add(int &x, int &y)
 {
 x += y;
 y = -(y);

 return x;
 }
22
5 內嵌(inline)函數
 函數很短時使用
1. 函數間引數的傳遞需要成本,若函數很短,使用內嵌函數可加
快程式執行
 #include <stdio.h>
 inline int max(int x, int y); // 將max宣告為inline function
 void main(void)
 {
 int i = 789, j = 876;
 printf("max(%d,%d) = %dn", i, j ,max(i,j));
 return;
 }
 inline int max(int x, int y) // 將max定義為inline function
 {
 if (x > y){
 return x;
 }
 else{
 return y;
 }
 }
23
 // 程式功能: inline函數
 #include <stdio.h>
 #include <cstdio>
 #include <string>
 using namespace std;
 inline int max(int x, int y)
 {return x > y ? x : y;}
 inline double max(double x, double y)
 {return x > y ? x : y;}
 inline string max(string &x, string &y)
 {return x > y ? x : y;}
 void main(void)
 {
 int i, j;
 i = 789;
 j = 876;
 printf("max(%d,%d) = %dn", i, j ,max(i,j));
 double d1, d2;
 d1 = 38.2;
 d2 = 88.7;
 printf("max(%g,%g) = %gn", d1, d2 ,max(d1,d2));
 string s1, s2;
 s1 = "object";
 s2 = "oriented";
 printf("max(%s,%s) = %sn", s1.c_str(), s2.c_str() ,max(s1,s2).c_str());
 return;
 }
24
6 遞迴函數(Recursive Function)
 C++ 允許函數自己呼叫自己
 稱之為遞迴(Recursive)
 // 程式功能: 遞回函數-求n!
 #include <stdio.h>
 long factorial(int n);
 void main(void)
 {
 printf("5! = %dn", factorial(5));
 return;
 }
 long factorial(int n)
 {
 if (n == 1){
 return 1; // 當n 等於1 時同址呼叫
 }
 else{
 return n * factorial(n-1); // 當n 大於1 時呼叫factorial(n-1);
 }
 }
25
7 主程式的引數
 // 程式功能: 測試argc, argv
 #include <stdio.h>
 #include <string>
 #include <cstdio>
 using namespace std;
 void main(int argc, char *argv[])
 {
 int i;
 string s[5];
 printf("argc = %dn", argc);
 for(i = 0; i < argc; i++){
 s[i] = argv[i];
 printf("argv[%d] = %sn", i, argv[i]);
 printf("s[%d] = %sn",i ,s[i]);
 }
 return;
 }
【執行結果】
D:PROGRAM>9_FUNC7.EXE abc def
argc = 3
argv[0] = D:PROGRAM9_FUNC7.EXE
s[0] = D:PROGRAM9_FUNC7.EXE
argv[1] = abc
s[1] = abc
argv[2] = def
s[2] = def
26
8.1內建函式: Math Library Functions
 Global functions
 Do not belong to a particular class
 Have function prototypes placed in header files
 Can be reused in any program that includes the header
file and that can link to the function’s object code
 Example: sqrt in <cmath> header file
 sqrt( 900.0 )
 All functions in <cmath> are global functions
27
Function Description Example
ceil( x ) rounds x to the smallest
integer not less than x
ceil( 9.2 ) is 10.0
ceil( -9.8 ) is -9.0
cos( x ) trigonometric cosine of x
(x in radians)
cos( 0.0 ) is 1.0
exp( x ) exponential function ex
exp( 1.0 ) is 2.71828
exp( 2.0 ) is 7.38906
fabs( x ) absolute value of x fabs( 5.1 ) is 5.1
fabs( 0.0 ) is 0.0
fabs( -8.76 ) is 8.76
floor( x ) rounds x to the largest integer not
greater than x
floor( 9.2 ) is 9.0
floor( -9.8 ) is -10.0
fmod( x, y ) remainder of x/y as a floating-point
number
fmod( 2.6, 1.2 ) is 0.2
log( x ) natural logarithm of x
(base e)
log( 2.718282 ) is 1.0
log( 7.389056 ) is 2.0
log10( x ) logarithm of x (base 10) log10( 10.0 ) is 1.0
log10( 100.0 ) is 2.0
pow( x, y ) x raised to power y (xy
) pow( 2, 7 ) is 128
pow( 9, .5 ) is 3
sin( x ) trigonometric sine of x
(x in radians)
sin( 0.0 ) is 0
sqrt( x ) square root of x (where x is a
nonnegative value)
sqrt( 9.0 ) is 3.0
tan( x ) trigonometric tangent of x
(x in radians)
tan( 0.0 ) is 0
8.2 C++ Standard Library Header
Files
 C++ Standard Library header files
 Each contains a portion of the Standard Library
 Function prototypes for the related functions
 Definitions of various class types and functions
 Constants needed by those functions
 "Instruct" the compiler on how to interface with
library and user-written components
 Header file names ending in .h
 Are "old-style" header files
 Superseded by the C++ Standard Library header files
28
C++ Standard Library header files. (Part 1 of 4)
C++ Standard
Library header file
Explanation
<iostream> Contains function prototypes for the C++ standard input and
standard output functions, introduced in Chapter 2, and is
covered in more detail in Chapter 15, Stream Input/Output. This
header file replaces header file <iostream.h>.
<iomanip> Contains function prototypes for stream manipulators that
format streams of data. This header file is first used in
Section 4.9 and is discussed in more detail in Chapter 15, Stream
Input/Output. This header file replaces header file
<iomanip.h>.
<cmath> Contains function prototypes for math library functions
(discussed in Section 6.3). This header file replaces header file
<math.h>.
<cstdlib> Contains function prototypes for conversions of numbers to text,
text to numbers, memory allocation, random numbers and
various other utility functions. Portions of the header file are
covered in Section 6.7; Chapter 11, Operator Overloading;
String and Array Objects; Chapter 16, Exception Handling;
Chapter 19, Web Programming; Chapter 22, Bits, Characters,
C-Strings and structs; and Appendix E, C Legacy Code
Topics. This header file replaces header file <stdlib.h>.
29
C++ Standard Library header files. (Part 2 of 4)
C++ Standard
Library header file
Explanation
<ctime> Contains function prototypes and types for manipulating the time and
date. This header file replaces header file <time.h>. This header file
is used in Section 6.7.
<vector>,
<list>,
<deque>,
<queue>,
<stack>,
<map>,
<set>,
<bitset>
These header files contain classes that implement the C++ Standard
Library containers. Containers store data during a program’s
execution. The <vector> header is first introduced in Chapter 7,
Arrays and Vectors. We discuss all these header files in Chapter 23,
Standard Template Library (STL).
<cctype> Contains function prototypes for functions that test characters for
certain properties (such as whether the character is a digit or a
punctuation), and function prototypes for functions that can be used to
convert lowercase letters to uppercase letters and vice versa. This
header file replaces header file <ctype.h>. These topics are
discussed in Chapter 8, Pointers and Pointer-Based Strings, and
Chapter 22, Bits, Characters, C-Strings and structs.
<cstring> Contains function prototypes for C-style string-processing functions.
This header file replaces header file <string.h>. This header file is
used in Chapter 11, Operator Overloading; String and Array Objects.
30
C++ Standard Library header files. (Part 3 of 4)
C++ Standard
Library header file
Explanation
<typeinfo> Contains classes for runtime type identification (determining
data types at execution time). This header file is discussed in
Section 13.8.
<exception>,
<stdexcept>
These header files contain classes that are used for exception
handling (discussed in Chapter 16).
<memory> Contains classes and functions used by the C++ Standard
Library to allocate memory to the C++ Standard Library
containers. This header is used in Chapter 16, Exception
Handling.
<fstream> Contains function prototypes for functions that perform input
from files on disk and output to files on disk (discussed in
Chapter 17, File Processing). This header file replaces header file
<fstream.h>.
<string> Contains the definition of class string from the C++ Standard
Library (discussed in Chapter 18).
<sstream> Contains function prototypes for functions that perform input
from strings in memory and output to strings in memory
(discussed in Chapter 18, Class string and String Stream
Processing).
<functional> Contains classes and functions used by C++ Standard Library
algorithms. This header file is used in Chapter 23.
31
C++ Standard Library header files. (Part 4 of 4)
C++ Standard Library
header file
Explanation
<iterator> Contains classes for accessing data in the C++ Standard Library
containers. This header file is used in Chapter 23, Standard Template
Library (STL).
<algorithm> Contains functions for manipulating data in C++ Standard Library
containers. This header file is used in Chapter 23.
<cassert> Contains macros for adding diagnostics that aid program debugging.
This replaces header file <assert.h> from pre-standard C++. This
header file is used in Appendix F, Preprocessor.
<cfloat> Contains the floating-point size limits of the system. This header file
replaces header file <float.h>.
<climits> Contains the integral size limits of the system. This header file replaces
header file <limits.h>.
<cstdio> Contains function prototypes for the C-style standard input/output
library functions and information used by them. This header file
replaces header file <stdio.h>.
<locale> Contains classes and functions normally used by stream processing to
process data in the natural form for different languages (e.g.,
monetary formats, sorting strings, character presentation, etc.).
<limits> Contains classes for defining the numerical data type limits on each
computer platform.
<utility> Contains classes and functions that are used by many C++ Standard
Library header files.
32
33
8 函數的應用
(too old, some need update)
 內建函數:亂數產生器rand( ) 與 random(n)
 #include <stdlib.h>
 內建函數:日期與時間getdate( ) 與gettime( )
 #include <dos.h>
 內建函數: ceil(x) 與floor(x)
 #include <math.h>
 內建函數: 平方根 sqrt(x)
 內建函數: 次方 pow(x, y)
34
 // 程式功能: 亂數產生器
 #include <stdio.h>
 #include <stdlib.h>
 void main(void)
 {
 int i;

 printf("產生個亂數...n");
 for(i = 0; i <= 5; i++){
 printf(" 第%d 個亂數值為%dn", i+1, rand());
 }
 printf("n");
 printf("產生個亂數,亂數值必須介於到之間...n");
 for(i = 0; i <= 5; i++){
 printf(" 第%d 個亂數值為%dn", i+1, rand()%6);
 }
 return;
 }
35
 // 程式功能: 取得系統日期與時間
 #include <stdio.h>
 #include <dos.h>
 void main(void)
 {
 struct date current_date;
 getdate(&current_date);
 printf("現在的日期是...");
 printf("%d 年", current_date.da_year);
 printf("%d 月", int(current_date.da_mon));
 printf("%d 日nn ", int(current_date.da_day));
 struct time current_time;
 gettime(&current_time);
 printf("現在的時間是... ");
 printf("%d 時", int(current_time.ti_hour));
 printf("%d 分", int(current_time.ti_min));
 printf("%d 秒n", int(current_time.ti_sec));
 return;
 }
36
 // 程式功能: ceil() 與 floor()
 #include <stdio.h>
 #include <math.h>
 void main(void)
 {
 double d = 88.3;
 printf("大於等於88.3 的最小整數為%dn", int(ceil(d)));
 printf("小於等於88.3 的最大整數為%dn", int(floor(d)));
 return;
 }
37
 // 程式功能: 取得浮動點數 d 的平方根
 #include <stdio.h>
 #include <math.h>
 void main(void)
 {
 double d1 = 99.9;
 double d2 = 144.0;

 printf("%g的平方跟為%gn", d1, sqrt(d1));
 printf("%g的平方跟為%gn", d2, sqrt(d2));
 return;
 }
38
 // 程式功能: 計算浮動點數x的y次方值
 #include <stdio.h>
 #include <math.h>
 void main(void)
 {
 double x = 3.0;
 double y = 2.0;

 printf("%g的%g次方為%gn", x, y, pow(x,y));
 x = 3.3;
 y = 2.2;
 printf("%g的%g次方為%gn", x, y, pow(x,y));
 return;
 }
39
9.1 函數的應用:
堆疊的實作(使用陣列)
 // 程式功能: 堆疊
 #include <stdio.h>
 #define STACK_SIZE 80 // 堆疊容量
 int top = -1; // 堆疊的top指標
 char stack[STACK_SIZE]; // 堆疊的宣告
 void push(char c); // 將資料放入堆疊
 char pop(void); // 從堆疊取出資料
 void main(void)
 {
 int i = 0;
 char s[] = "object oriented programming language";
 printf("輸入為:%sn", s);
 printf("輸出為:");
 while(s[i] != '0')
 push(s[i++]);
 while(top >= 0)
 printf("%c",pop());
 printf("n");
 return;
 }
40
 void push(char c)
 {
 if(top < STACK_SIZE)
 stack[++top] = c;
 else
 printf("stack 已滿,無法放入資料n");
 }

 // 從堆疊取出資料
 char pop(void)
 {
 if(top >= 0)
 return (stack[top--]);
 else
 printf("stack 已空,無法取出資料n");
 }
接續上一頁
41
9.1 函數的應用:
堆疊的實作(使用鏈結串列)
 // 程式功能:用鏈結串列結構來實作stack
 #include <stdio.h>
 void create_empty_stack(void);
 void push(char c);
 char pop(void);
 struct node{ // 定義一個節點 node
 char data; // data用來存放字元資料
 struct node *next; // 指向另一個節點的指標
 };
 node *top, *rear; // top 是一個指向front的節點指標
 // rear 是一個指向rear 的節點指標
42
 void main(void)
 {
 int i = 0;
 char s[] = "object oriented programming language";
 printf("輸入為:%sn", s);
 printf("輸出為:");
 create_empty_stack(); // 產生一個空堆疊
 while(s[i] != '0')
 push(s[i++]);

 while(top->next != NULL)
 printf("%c",pop());
 printf("n");

 return;
 }
接續上一頁
43
 // 產生一個空堆疊,它只有top及rear兩個節點
 void create_empty_stack(void)
 {
 top = new (struct node);
 top->next = rear;
 rear = new (struct node);
 rear->next = rear;
 }
 // 將字元 c 放入堆疊
 void push(char c)
 {
 struct node *new_node;

 new_node = new (struct node);
 new_node->data = c;
 new_node->next = top->next;
 top->next = new_node;
 }
接續上一頁
44
 // 自堆疊頂端取出資料
 char pop(void)
 {
 char c;
 struct node *temp_node;

 temp_node = top->next;
 top->next = temp_node->next;
 c = temp_node->data;
 delete temp_node;
 return(c);
 }
接續上一頁
45
作業
 設計一個函數F(N),計算第N項的費氏級數。
費氏級數定義如下︰
F(N) = F(N-1) + F(N-2),F(0) = 0,F(1)=1。
 請分別使用遞迴函數(Recursion)和疊代(Iteration)
的方式來實作F(N)。
 測試時請變動N值來比較兩個程式執行所花費的時
間

Chapter 7 functions (c)

  • 1.
  • 2.
    2 本章主題  函數的定義與宣告  變數的能見度 參數的傳遞  內嵌(inline)函數  遞迴函數(Recursive Function)  主程式的引數  函數的應用
  • 3.
    3 1 函數的定義與宣告  定義函數的語法】 函數型態 函數名稱(資料型態 參數1,資料型態 參數2, …)  {  // 函數主體  [return expression ;]  }  函數型態  函數名稱  參數列  函數主體
  • 4.
    4 函數的定義與宣告  【呼叫函數的語法】  函數名稱(引數1,引數2,…);  函數的宣告--函數原型  函數型態 函數名稱(資料型態 參數1,資料型態 參數2, …); int main() { ... i = max(a,b) ; ... } int max(int x,int y) { if (x > y) return x ; else return y ; } 呼叫函數 返回
  • 5.
  • 6.
    6 1. // 程式功能:計算 n! 2. #include <stdio.h> 3. long factorial(int n); //宣告factorial函數 4. int main() 5. { 6. int n = 1; 7. printf("請輸入正整數n:"); 8. scanf("%d", &n); 9. printf("n"); 10. printf("n!=%d" ,factorial(n)); //呼叫factorial函數 11. return 0; 12. } 13. long factorial(int n) //定義factorial函數 14. { 15. long factorial = 1; 16. while(n > 1) 17. factorial *= n--; 18. return factorial; 19. }
  • 7.
    7 2 C的程式架構  #include< >  #define  資料型態 函數1(參數列); // 函數原型,即函數的宣告  資料型態 函數2(參數列); // 函數原型,即函數的宣告  ...  全域變數的宣告;  資料型態 main(參數列) // 定義main函數  {  私有變數的宣告;  函數主體;  return 運算式或值;  }  資料型態 函數1(參數列) // 定義函數1  {  私有變數的宣告;  函數主體;  return 運算式或值;  }  資料型態 函數2(參數列) // 定義函數2  {  私有變數的宣告;  函數主體;  return 運算式或值;  }
  • 8.
    8 3 變數的能見度(存活空間)  全域(Global)變數 全域變數可以在整個程式中使用  私有(Private)變數  從宣告處開始,到該函式結束為止  { }  靜態 (Static) 變數  從宣告處開始,到該函式結束為止  函式結束時,該變數會被保留再記憶體裡,下次執行該函式 時,該變數不會被重新設定,而以前一次保留下來的值運作。  範疇運算子(::)  若在函數內想使用全域變數可使用範疇運算子  ::
  • 9.
    9 1. // 程式功能:測試全域變數及私有變數 2. #include <stdio.h> 3. void func1(void); 4. void func2(void); 5. int i = 1000; // i為全域變數 6. void main(void) 7. { 8. int i = 0, j = 0 , k = 0; // i,j,k為main( )的私有變數 9. printf("main().i = %d" ,i); 10. printf(",main().j = %d" ,j); 11. printf(",main().k = %dn" ,k); 12. func1() ; // 呼叫func1( ),不傳遞引數 13. printf("main().i = %d" ,i); 14. printf(",main().j = %d" ,j); 15. printf(",main().k = %dn" ,k); 16. return; 17. }
  • 10.
    10 1. void func1(void) 2.{ 3. int i = 88, j = 88; // i,j為func1( )的私有變數 4. printf(" 【進入func1】n"); 5. printf(" func1().i = %d" ,i); 6. printf(",func1().j = %dn" ,j); 7. func2(); // 呼叫func2( ),不傳遞引數 8. func2(); 9. printf(" func1().i = %d" ,i); 10. printf(",func1().j = %dn" ,j); 11. printf(" 【離開func1】n"); 12. return; 13. } 14. void func2(void) 15. { 16. int j = 999; // j為func2( )的私有變數 17. static int k = 999; // k為func2( )的靜態私有變數 18. printf(" 【進入func2】n"); 19. printf(" func2().i = %d" ,i); 20. printf(",func2().j = %d" ,j); 21. printf(",func2().k = %dn" ,k); 22. printf(" 【離開func2】n"); 23. i++; 24. j++; 25. k++; 26. return; 27. } 接續上一頁
  • 11.
    11  // 程式功能:全域變數的使用 1. #include <stdio.h> 2. int i = 1000; // i為全域變數 3. void main(void) 4. { 5. int i = 0; // i 為main( )的私有變數 6. 7. printf("私有.i = %dn", i); 8. printf("全域.i = %dn", ::i); 9. 10. return; 11. }
  • 12.
    12 4 參數的傳遞  以值傳遞(CallBy Value)  以址傳遞(Call By Address)  以參考值傳遞(Call By Reference)
  • 13.
    13 以值傳遞(Call By Value) int i = 789, j = 876 ,r;  r = add(80, 90);  printf("add(80,90) = %dn", r);  printf("add(%d,%d) = %dn", i, j, add(i,j)); int add(int x, int y) { x += y; return x; } 【執行結果】 add(80,90) = 170 add(789,876) = 1665  參數傳遞時會產生一副本,將副本 傳給函數,函數中數值改變不會影 響原本的變數值
  • 14.
    14 1. // 程式功能:測試以值傳遞  #include <stdio.h>  #include <conio.h>  #include <cstdio>  #include <string>  using namespace std;  int add(int, int); // 函數原型也可以如此寫  string add(string, string);  void main(void)  {  int i = 789, j = 876 ,r;  string x = "object";  string y = "oriented";  r = add(80,90) ;  printf("add(80,90) = %dn", r);  printf("add(%d,%d) = %dn", i, j, add(i,j));  printf("add(%s,%s) = %sn", x.c_str(), y.c_str(), add(x, y).c_str());  _getch(); return;  }  int add(int x, int y)  {  x += y;  return x;  }  string add(string x, string y)  {  x += (" " + y);  return x;  }
  • 15.
    15 以址傳遞(Call By Address) 1.int i = 789, j = 876; 2. printf("i=%dn", i); 3. printf("j=%dn", j); 4. printf("i+j=%dn", add(&i, &j)); 5. printf("i=%dn", i); 6. printf("j=%dnn", j); int add(int *x, int *y) { *x += *y; *y = -(*y); return *x; } 【執行結果】 i = 789 j = 876 i + j = 1665 i = 1665 j = -876  參數傳遞時將引數傳遞給函數參數, 函數執行完畢後在將參數值傳回給 呼叫者。數值改變會影響原本的變 數值
  • 16.
    16 1. // 程式功能:測試以址傳遞--以整數及字串為例  #include <stdio.h>  #include <conio.h>  #include <cstdio>  #include <string>  using namespace std;  int add(int*, int*); // 函數原型  string add(string*, string*); // 函數原型  void main(void)  {  int i = 789, j = 876;  string x = "object";  string y = "oriented";  printf("i = %dn",i);  printf("j = %dn",j);  printf("i + j = %dn", add(&i, &j)); // 以址傳遞  printf("i = %dn",i);  printf("j = %dnn",j);  printf("x = %sn", x.c_str());  printf("y = %sn", y.c_str());  printf("x + y = %sn", add(&x, &y).c_str()); // 以址傳遞  printf("x = %sn", x.c_str());  printf("y = %snn", y.c_str());  printf("n按<<Enter>>結束程式."); _getch(); return;  }
  • 17.
    17 接續上一頁  int add(int*x, int *y)  {  *x += *y;  *y = -(*y);   return *x;  }  string add(string *x, string *y)  {  *x += (" " + *y);  *y = "change";   return *x;  }
  • 18.
    18 1. // 程式功能:測試以址傳遞--以陣列為例 2. #include <stdio.h> 3. #include <iomanip> 4. #include <cstdio> 5. using namespace std; 6. void printf_score(string s, int a[], int len); // 函數原型 7. void add_score1(int *a, int len); // 函數原型,以指標為參數 8. void add_score2(int a[], int len); // 函數原型,以陣列為參數 9. void main(void) 10. { 11. int len = 0; 12. int score[] = {85,73,67,90,81,78,90,66,88,78}; 13. len = sizeof(score)/sizeof(score[0]); // 取得陣列元素個數 14. printf_score("呼叫前: ", score, len); 15. add_score1(score,len); // 傳遞陣列 16. printf_score("呼叫後: ", score, len); 17. printf("n"); 18. printf_score("呼叫前: ", score, len); 19. add_score2(score,len); // 傳遞陣列 20. printf_score("呼叫後: ", score, len); 21. return; 22. }
  • 19.
    19 23. void add_score1(int*a, int len) // 每人加5 分 24. { 25. int i = 0; 26. for(i = 0 ; i < len ; i++){ 27. *a++ += 5; 28. } 29. return; 30. } 31. void add_score2(int a[], int len) // 將全班最高分調到分,其餘遞增 32. { 33. int i = 0, j = 0, max = 0; 34. for(i = 0; i < len; i++){ 35. max = (a[i] > max) ? a[i] : max; // 單行條件式 36. } 37. j = 100 - max; 38. for(i = 0 ;i < len; i++){ 39. a[i] += j; 40. } 41. return ; 42. } 43. void printf_score(string s, int a[], int len) // 印出全班成績 44. { 45. printf("%s",s.c_str()); 46. for(int i = 0; i < len; i++){ 47. printf("%5d",a[i]); 48. } 49. printf("n"); 50. } 接續上一頁
  • 20.
    20 以參考值傳遞(Call By Reference) int i = 789, j = 876;   printf("i=%dn",i);  printf("j=%dn",j);  printf("i+j=%dn",add(i,j));  printf("i=%dn",i);  printf("j=%dnn",j); int add(int &x, int &y) { x += y; y = -(y); return x; }【執行結果】 i = 789 j = 876 i + j = 1665 i = 1665 j = -876  將函數參數視為引數的別名,函數 中數值改變會影響原本的變數值
  • 21.
    21 1. // 程式功能:測試以參考值傳遞  #include <stdio.h>  int add(int &x, int &y); // 函數原型  void main(void)  {  int i = 789, j = 876;   printf("i = %dn",i);  printf("j = %dn",j);  printf("i + j = %dn",add(i,j));  printf("i = %dn",i);  printf("j = %dnn",j);  return;  }  int add(int &x, int &y)  {  x += y;  y = -(y);   return x;  }
  • 22.
    22 5 內嵌(inline)函數  函數很短時使用 1.函數間引數的傳遞需要成本,若函數很短,使用內嵌函數可加 快程式執行  #include <stdio.h>  inline int max(int x, int y); // 將max宣告為inline function  void main(void)  {  int i = 789, j = 876;  printf("max(%d,%d) = %dn", i, j ,max(i,j));  return;  }  inline int max(int x, int y) // 將max定義為inline function  {  if (x > y){  return x;  }  else{  return y;  }  }
  • 23.
    23  // 程式功能:inline函數  #include <stdio.h>  #include <cstdio>  #include <string>  using namespace std;  inline int max(int x, int y)  {return x > y ? x : y;}  inline double max(double x, double y)  {return x > y ? x : y;}  inline string max(string &x, string &y)  {return x > y ? x : y;}  void main(void)  {  int i, j;  i = 789;  j = 876;  printf("max(%d,%d) = %dn", i, j ,max(i,j));  double d1, d2;  d1 = 38.2;  d2 = 88.7;  printf("max(%g,%g) = %gn", d1, d2 ,max(d1,d2));  string s1, s2;  s1 = "object";  s2 = "oriented";  printf("max(%s,%s) = %sn", s1.c_str(), s2.c_str() ,max(s1,s2).c_str());  return;  }
  • 24.
    24 6 遞迴函數(Recursive Function) C++ 允許函數自己呼叫自己  稱之為遞迴(Recursive)  // 程式功能: 遞回函數-求n!  #include <stdio.h>  long factorial(int n);  void main(void)  {  printf("5! = %dn", factorial(5));  return;  }  long factorial(int n)  {  if (n == 1){  return 1; // 當n 等於1 時同址呼叫  }  else{  return n * factorial(n-1); // 當n 大於1 時呼叫factorial(n-1);  }  }
  • 25.
    25 7 主程式的引數  //程式功能: 測試argc, argv  #include <stdio.h>  #include <string>  #include <cstdio>  using namespace std;  void main(int argc, char *argv[])  {  int i;  string s[5];  printf("argc = %dn", argc);  for(i = 0; i < argc; i++){  s[i] = argv[i];  printf("argv[%d] = %sn", i, argv[i]);  printf("s[%d] = %sn",i ,s[i]);  }  return;  } 【執行結果】 D:PROGRAM>9_FUNC7.EXE abc def argc = 3 argv[0] = D:PROGRAM9_FUNC7.EXE s[0] = D:PROGRAM9_FUNC7.EXE argv[1] = abc s[1] = abc argv[2] = def s[2] = def
  • 26.
    26 8.1內建函式: Math LibraryFunctions  Global functions  Do not belong to a particular class  Have function prototypes placed in header files  Can be reused in any program that includes the header file and that can link to the function’s object code  Example: sqrt in <cmath> header file  sqrt( 900.0 )  All functions in <cmath> are global functions
  • 27.
    27 Function Description Example ceil(x ) rounds x to the smallest integer not less than x ceil( 9.2 ) is 10.0 ceil( -9.8 ) is -9.0 cos( x ) trigonometric cosine of x (x in radians) cos( 0.0 ) is 1.0 exp( x ) exponential function ex exp( 1.0 ) is 2.71828 exp( 2.0 ) is 7.38906 fabs( x ) absolute value of x fabs( 5.1 ) is 5.1 fabs( 0.0 ) is 0.0 fabs( -8.76 ) is 8.76 floor( x ) rounds x to the largest integer not greater than x floor( 9.2 ) is 9.0 floor( -9.8 ) is -10.0 fmod( x, y ) remainder of x/y as a floating-point number fmod( 2.6, 1.2 ) is 0.2 log( x ) natural logarithm of x (base e) log( 2.718282 ) is 1.0 log( 7.389056 ) is 2.0 log10( x ) logarithm of x (base 10) log10( 10.0 ) is 1.0 log10( 100.0 ) is 2.0 pow( x, y ) x raised to power y (xy ) pow( 2, 7 ) is 128 pow( 9, .5 ) is 3 sin( x ) trigonometric sine of x (x in radians) sin( 0.0 ) is 0 sqrt( x ) square root of x (where x is a nonnegative value) sqrt( 9.0 ) is 3.0 tan( x ) trigonometric tangent of x (x in radians) tan( 0.0 ) is 0
  • 28.
    8.2 C++ StandardLibrary Header Files  C++ Standard Library header files  Each contains a portion of the Standard Library  Function prototypes for the related functions  Definitions of various class types and functions  Constants needed by those functions  "Instruct" the compiler on how to interface with library and user-written components  Header file names ending in .h  Are "old-style" header files  Superseded by the C++ Standard Library header files 28
  • 29.
    C++ Standard Libraryheader files. (Part 1 of 4) C++ Standard Library header file Explanation <iostream> Contains function prototypes for the C++ standard input and standard output functions, introduced in Chapter 2, and is covered in more detail in Chapter 15, Stream Input/Output. This header file replaces header file <iostream.h>. <iomanip> Contains function prototypes for stream manipulators that format streams of data. This header file is first used in Section 4.9 and is discussed in more detail in Chapter 15, Stream Input/Output. This header file replaces header file <iomanip.h>. <cmath> Contains function prototypes for math library functions (discussed in Section 6.3). This header file replaces header file <math.h>. <cstdlib> Contains function prototypes for conversions of numbers to text, text to numbers, memory allocation, random numbers and various other utility functions. Portions of the header file are covered in Section 6.7; Chapter 11, Operator Overloading; String and Array Objects; Chapter 16, Exception Handling; Chapter 19, Web Programming; Chapter 22, Bits, Characters, C-Strings and structs; and Appendix E, C Legacy Code Topics. This header file replaces header file <stdlib.h>. 29
  • 30.
    C++ Standard Libraryheader files. (Part 2 of 4) C++ Standard Library header file Explanation <ctime> Contains function prototypes and types for manipulating the time and date. This header file replaces header file <time.h>. This header file is used in Section 6.7. <vector>, <list>, <deque>, <queue>, <stack>, <map>, <set>, <bitset> These header files contain classes that implement the C++ Standard Library containers. Containers store data during a program’s execution. The <vector> header is first introduced in Chapter 7, Arrays and Vectors. We discuss all these header files in Chapter 23, Standard Template Library (STL). <cctype> Contains function prototypes for functions that test characters for certain properties (such as whether the character is a digit or a punctuation), and function prototypes for functions that can be used to convert lowercase letters to uppercase letters and vice versa. This header file replaces header file <ctype.h>. These topics are discussed in Chapter 8, Pointers and Pointer-Based Strings, and Chapter 22, Bits, Characters, C-Strings and structs. <cstring> Contains function prototypes for C-style string-processing functions. This header file replaces header file <string.h>. This header file is used in Chapter 11, Operator Overloading; String and Array Objects. 30
  • 31.
    C++ Standard Libraryheader files. (Part 3 of 4) C++ Standard Library header file Explanation <typeinfo> Contains classes for runtime type identification (determining data types at execution time). This header file is discussed in Section 13.8. <exception>, <stdexcept> These header files contain classes that are used for exception handling (discussed in Chapter 16). <memory> Contains classes and functions used by the C++ Standard Library to allocate memory to the C++ Standard Library containers. This header is used in Chapter 16, Exception Handling. <fstream> Contains function prototypes for functions that perform input from files on disk and output to files on disk (discussed in Chapter 17, File Processing). This header file replaces header file <fstream.h>. <string> Contains the definition of class string from the C++ Standard Library (discussed in Chapter 18). <sstream> Contains function prototypes for functions that perform input from strings in memory and output to strings in memory (discussed in Chapter 18, Class string and String Stream Processing). <functional> Contains classes and functions used by C++ Standard Library algorithms. This header file is used in Chapter 23. 31
  • 32.
    C++ Standard Libraryheader files. (Part 4 of 4) C++ Standard Library header file Explanation <iterator> Contains classes for accessing data in the C++ Standard Library containers. This header file is used in Chapter 23, Standard Template Library (STL). <algorithm> Contains functions for manipulating data in C++ Standard Library containers. This header file is used in Chapter 23. <cassert> Contains macros for adding diagnostics that aid program debugging. This replaces header file <assert.h> from pre-standard C++. This header file is used in Appendix F, Preprocessor. <cfloat> Contains the floating-point size limits of the system. This header file replaces header file <float.h>. <climits> Contains the integral size limits of the system. This header file replaces header file <limits.h>. <cstdio> Contains function prototypes for the C-style standard input/output library functions and information used by them. This header file replaces header file <stdio.h>. <locale> Contains classes and functions normally used by stream processing to process data in the natural form for different languages (e.g., monetary formats, sorting strings, character presentation, etc.). <limits> Contains classes for defining the numerical data type limits on each computer platform. <utility> Contains classes and functions that are used by many C++ Standard Library header files. 32
  • 33.
    33 8 函數的應用 (too old,some need update)  內建函數:亂數產生器rand( ) 與 random(n)  #include <stdlib.h>  內建函數:日期與時間getdate( ) 與gettime( )  #include <dos.h>  內建函數: ceil(x) 與floor(x)  #include <math.h>  內建函數: 平方根 sqrt(x)  內建函數: 次方 pow(x, y)
  • 34.
    34  // 程式功能:亂數產生器  #include <stdio.h>  #include <stdlib.h>  void main(void)  {  int i;   printf("產生個亂數...n");  for(i = 0; i <= 5; i++){  printf(" 第%d 個亂數值為%dn", i+1, rand());  }  printf("n");  printf("產生個亂數,亂數值必須介於到之間...n");  for(i = 0; i <= 5; i++){  printf(" 第%d 個亂數值為%dn", i+1, rand()%6);  }  return;  }
  • 35.
    35  // 程式功能:取得系統日期與時間  #include <stdio.h>  #include <dos.h>  void main(void)  {  struct date current_date;  getdate(&current_date);  printf("現在的日期是...");  printf("%d 年", current_date.da_year);  printf("%d 月", int(current_date.da_mon));  printf("%d 日nn ", int(current_date.da_day));  struct time current_time;  gettime(&current_time);  printf("現在的時間是... ");  printf("%d 時", int(current_time.ti_hour));  printf("%d 分", int(current_time.ti_min));  printf("%d 秒n", int(current_time.ti_sec));  return;  }
  • 36.
    36  // 程式功能:ceil() 與 floor()  #include <stdio.h>  #include <math.h>  void main(void)  {  double d = 88.3;  printf("大於等於88.3 的最小整數為%dn", int(ceil(d)));  printf("小於等於88.3 的最大整數為%dn", int(floor(d)));  return;  }
  • 37.
    37  // 程式功能:取得浮動點數 d 的平方根  #include <stdio.h>  #include <math.h>  void main(void)  {  double d1 = 99.9;  double d2 = 144.0;   printf("%g的平方跟為%gn", d1, sqrt(d1));  printf("%g的平方跟為%gn", d2, sqrt(d2));  return;  }
  • 38.
    38  // 程式功能:計算浮動點數x的y次方值  #include <stdio.h>  #include <math.h>  void main(void)  {  double x = 3.0;  double y = 2.0;   printf("%g的%g次方為%gn", x, y, pow(x,y));  x = 3.3;  y = 2.2;  printf("%g的%g次方為%gn", x, y, pow(x,y));  return;  }
  • 39.
    39 9.1 函數的應用: 堆疊的實作(使用陣列)  //程式功能: 堆疊  #include <stdio.h>  #define STACK_SIZE 80 // 堆疊容量  int top = -1; // 堆疊的top指標  char stack[STACK_SIZE]; // 堆疊的宣告  void push(char c); // 將資料放入堆疊  char pop(void); // 從堆疊取出資料  void main(void)  {  int i = 0;  char s[] = "object oriented programming language";  printf("輸入為:%sn", s);  printf("輸出為:");  while(s[i] != '0')  push(s[i++]);  while(top >= 0)  printf("%c",pop());  printf("n");  return;  }
  • 40.
    40  void push(charc)  {  if(top < STACK_SIZE)  stack[++top] = c;  else  printf("stack 已滿,無法放入資料n");  }   // 從堆疊取出資料  char pop(void)  {  if(top >= 0)  return (stack[top--]);  else  printf("stack 已空,無法取出資料n");  } 接續上一頁
  • 41.
    41 9.1 函數的應用: 堆疊的實作(使用鏈結串列)  //程式功能:用鏈結串列結構來實作stack  #include <stdio.h>  void create_empty_stack(void);  void push(char c);  char pop(void);  struct node{ // 定義一個節點 node  char data; // data用來存放字元資料  struct node *next; // 指向另一個節點的指標  };  node *top, *rear; // top 是一個指向front的節點指標  // rear 是一個指向rear 的節點指標
  • 42.
    42  void main(void) {  int i = 0;  char s[] = "object oriented programming language";  printf("輸入為:%sn", s);  printf("輸出為:");  create_empty_stack(); // 產生一個空堆疊  while(s[i] != '0')  push(s[i++]);   while(top->next != NULL)  printf("%c",pop());  printf("n");   return;  } 接續上一頁
  • 43.
    43  // 產生一個空堆疊,它只有top及rear兩個節點 void create_empty_stack(void)  {  top = new (struct node);  top->next = rear;  rear = new (struct node);  rear->next = rear;  }  // 將字元 c 放入堆疊  void push(char c)  {  struct node *new_node;   new_node = new (struct node);  new_node->data = c;  new_node->next = top->next;  top->next = new_node;  } 接續上一頁
  • 44.
    44  // 自堆疊頂端取出資料 char pop(void)  {  char c;  struct node *temp_node;   temp_node = top->next;  top->next = temp_node->next;  c = temp_node->data;  delete temp_node;  return(c);  } 接續上一頁
  • 45.
    45 作業  設計一個函數F(N),計算第N項的費氏級數。 費氏級數定義如下︰ F(N) =F(N-1) + F(N-2),F(0) = 0,F(1)=1。  請分別使用遞迴函數(Recursion)和疊代(Iteration) 的方式來實作F(N)。  測試時請變動N值來比較兩個程式執行所花費的時 間