Make
each
day
count
要使⽤內建函式,必須在程式開頭處使⽤ #include 前置指令含入內建函
式的標頭檔
#include <stdio.h>
#include <math.h>
#define PI 3.14159
void std_func(){
double r;
int x;
printf("n x:角度值 t r:弳度值 t sin tt csc");
printf("n========================================================");
for(x = 30; x <= 150; x += 30){
r = PI * (x / 180.0);
printf("n %3d tt %.5f t %.5f t %.5f", x, r, sin(r), 1 / sin(r));
}
}
內建函式 2/2
5
Make
each
day
count
函式定義 (function definition) 就是函式的程式區塊,語法如下:
例如:
_Bool isPrime(int n) {
for (i = 2; i <= sqrt(n); i++) {
if (n % i == 0) break;
}
return (i > sqrt(n));
}
自訂函式 2/3
11
函式傳回值之資料型別,
若函式沒有傳回值則將ret_type指定為 void
自訂函式名稱
傳給函式的引數,其格式如同變數宣告;
如果沒有引數,則函式名稱後接空括號
指令敘述,
就是函式的實作 (implements)
有傳回值時,必須使用 return 敘述回傳資料
Make
each
day
count
呼叫函式
完成函式定義後,就可以將該函式當成⼀個新的指令敘述使⽤
_Bool isPrime(int); //函式原型宣告
int main(int argc, char* argv[]){
int num;
printf("輸入整數值:");
scanf("%d", &num);
if (isPrime(num))
printf("%d是質數", num);
else
printf("%d不是質數", num);
}
_Bool isPrime(int n){
for (i = 2; i <= sqrt(n); i++){
if (n % i == 0) break;
}
return (i > sqrt(n));
}
自訂函式 3/3
12
呼叫函式
返回主程式
Make
each
day
count
傳值呼叫 (call by value )
主程式把資料值複製⼀份給函式之引數保存 (另⼀個記憶體位置的值),因
此函式中不管如何存取引數資料,都不會影響到主程式的資料值
函式引數的傳遞方式 1/6
13
10
20
10
20
&num1
&a
&num2
&b
call_by_value(num1, num2);
主程式變數 函式引數
void call_by_value(int a,int b){
...
}
Make
each
day
count
void swap_by_value(int a, int b){
int temp;
printf("a = %d, b = %dn", a, b);
temp = a;
a = b;
b = temp;
printf("a = %d, b = %dn", a, b);
}
void main(){
int num1 = 10, num2 = 20;
printf("num1 = %d, num2 = %dn", num1, num2);
swap_by_value(num1, num2);
printf("num1 = %d, num2 = %dn", num1, num2);
}
函式引數的傳遞方式 2/6
14
Make
each
day
count
傳址呼叫 (call by address)
主程式把儲存資料的記憶體位置傳到函式之引數,因此引數與主程式是共
⽤同⼀個記憶體位置之資料,
void call_by_address(int* a, int* b){
...
}
函式引數的傳遞方式 3/6
15
10
20
&num1
&num2
&num1
&a
&num2
&b
call_by_address(&num1, &num2);
主程式變數 函式引數
*a
*b
&取址運算子:&num表示變數num的記憶體位址
*指標運算子:*a表示到變數a所指示的記憶體位址讀取資料
1
2
1
2
Make
each
day
count
int bubble_sort(int data[], int n){
int i, j, flag, temp;
for (i = 0; i < n - 1; i++){ //n個數字排序,只⽤n-1回合
flag = 0; //每回合清除交換旗號
for (j = 0; j < n – i - 1; j++) {
if (data[j] > data[j + 1]) {
temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
flag = 1; //表示發生過交換
}
}
if (flag == 0) break; //此回合沒有發生交換,表示資料己排序
}
}
Lab 設計泡泡排序函式 1/2
19
Make
each
day
count
測試泡泡排序
void main(){
int n, i;
int *data;
printf("Number of data: ");
scanf("%d", &n);
data = (int *)malloc(n * sizeof(int));
printf("Numbers to be sorted: ");
for(i = 0; i < n; i++)
scanf("%d", &data[i]);
printf("n");
bubble_sort(data, n);
printf("Numbers Sorted: ");
for(i = 0; i < n; i++)
printf("%d ", data[i]);
free(data);
}
Lab 設計泡泡排序函式 2/2
20
Make
each
day
count
#include <stdio.h>
void find_bound(int n, int data[], int *min, int *max){
//設計函式,從data[]找出最大值及最小值
}
void main(){
int i, n, max, min, *data;
printf("輸入資料個數:");
scanf("%d", &n);
data = (int *)malloc(n * sizeof(int));
printf("輸入%d筆整數值(數值間以空白鍵區隔):", n);
for (i = 0; i < n; i++) scanf("%d", &data[i]);
find_bound(...); //呼叫find_bound()函式,...必須改為參數群
printf("最大值為%d%,最小值為%d", max, min);
free(data);
}
實作練習 設計尋找極值函式 1/2
21
Make
each
day
count
遞迴函式, 簡單地說就是⼀個呼叫自己的函式
計算 1 加到 N
疊代 (iterative) 方式
int sum(int n){
int i, sum = 0;
for (i = 1; i <= n; i++)
sum = sum + i;
return sum;
}
遞迴函式 (Recursive) 1/6
23
Make
each
day
count
資料交換函式
void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
快速排序函式
void quick_sort(int data[], int left, int right){
int pivot, leftmark, rightmark;
if (left >= right) return;
pivot = data[left];
leftmark = left + 1;
rightmark = right;
Lab 快速排序 (Quick Sort) 3/5
31
left right
pivot
leftmark rightmark
Make
each
day
count
while (1){
while (leftmark <= right){
if (data[leftmark] > pivot) break;
leftmark++;
}
while (rightmark > left){
if (data[rightmark] < pivot) break;
rightmark--;
}
if (leftmark > rightmark) break;
swap(&data[leftmark], &data[rightmark]);
}
swap(&data[left], &data[rightmark]);
quick_sort(data, left, rightmark - 1);
quick_sort(data, rightmark + 1, right);
}
Lab 快速排序 (Quick Sort) 4/5
32
left right
pivot
leftmark rightmark
leftmark
rightmark
Make
each
day
count
測試快速排序
void main(){
int n, i;
int *data;
printf("Number of data: ");
scanf("%d", &n);
data = (int *)malloc(n*sizeof(int));
printf("Numbers to be sorted: ");
for(i = 0; i < n; i++){
scanf("%d", &data[i]);
}
printf("n");
quick_sort(data, 0, n);
printf("Numbers Sorted: ");
for(i = 0; i < n; i++){
printf("%d ", data[i]);
}
}
Lab 快速排序 (Quick Sort) 5/5
33
Make
each
day
count
有三根杆⼦A,B,C。A杆上有 N 個 (N>1) 穿孔圓盤,盤的尺寸由下
到上依次變小。要求按下列規則將所有圓盤移至 C 杆:
每次只能移動⼀個圓盤
大盤不能疊在小盤上面
提示:可將圓盤臨時置於 B 杆,也可將從 A 杆移出的圓盤重新移回 A 杆,
但都必須遵循上述兩條規則
Lab 解河內塔 1/4
34
Make
each
day
count
void hanoi(int n, char A, char B, char C){
if (n == 1) {
printf(“%3d: 將圓盤 %d 從 %c 移到 %cn", ++time, n, A, C);
}
else {
hanoi(n - 1, A, C, B);
printf(“%3d: 將圓盤 %d 從 %c 移到 %cn", ++time, n, A, C);
hanoi(n - 1, B, A, C);
}
}
Lab 解河內塔 4/4
37
Make
each
day
count
變數的有效範圍 (scope) 是指哪些程式碼可以存取此變數的值
變數的生命期 (life cycle)是變數的值會保留多久
C 程式如果擁有多個函式,變數在那裡宣告,決定變數的有效範圍及
生命期。C 語言的變數依照有效範圍可以分為兩種:
區域變數 (local variables)
在程式區塊中宣告的變數是⼀種區域變數,例如:在函式中宣告的變數或
參數,區域變數只能在宣告的函式中使⽤,在函式之外的程式碼並不能存
取此變數。
全域變數 (global variables)
在 C 程式檔的函式之外宣告的變數是⼀種全域變數,例如:在函式外宣告
變數,整個程式檔案都可以存取此變數,如果全域變數沒有指定初值,預
設值是 0
變數的有效範圍與生命期 1/8
38
Make
each
day
count
#include <stdio.h>
int x=10; //global x
int main(int argc, char** argv) {
int y = 20; //y local to block 1
...
for () {
int z = 30; //z local to block 2
...
}
}
void func(){
int x = 40; //x local to block 3
...
}
變數的有效範圍與生命期 2/8
39
1
2
3
Make
each
day
count
#include <stdio.h>
void myfunc() {
int x = 10; //區域變數
static int y = 10; //靜態區域變數
x++;
y++;
printf("x = %d, ty = %dn", x, y);
}
void main(int argc, char** argv) {
for (int i = 0; i < 5; i++)
myfunc();
}
變數的有效範圍與生命期 5/8
42