11. Make
each
day
count
陣列在宣告後,使用指定敘述指定陣列元素值,語法如下:
陣列名稱[索引] = 變數、運算式或常數值;
陣列索引值是從 0 開始
int n;
printf("輸入小考次數:");
scanf("%d", &n);
int i, quizzes[n], sum = 0;
float average;
printf("請輸入%d筆小考成績(整數值,數值間以空白鍵區隔):", n);
for (i = 0; i < n; i++) {
scanf("%d", &quizzes[i]);
sum += quizzes[i]; //計算小考成績總和
}
average = (float)sum / n; //計算小考平均成績
printf("小考平均成績為:%0.1f", average);
讀取陣列元素值
11
14. Make
each
day
count
void sequential_search(){
int data[] = {3, 4, 1, 7, 6, 15, 9, 8, 12};
int i, fnum, n;
n = sizeof(data) / sizeof(data[0]);
printf("n輸入欲搜尋的整數:");
scanf("%d", &fnum);
for (i = 0; i < n; i++) {
if (fnum == data[i]) {
printf("n%d在陣列元素data[%d]內", fnum, i);
break;
}
}
if (i == n) printf("n%d資料不在陣列中", fnum);
}
資料搜尋 2/4
14
15. Make
each
day
count
二分搜尋法 (Binary Search)
如果資料已先排序過,則可使用二分法來進行搜尋
二分法是將資料分成兩部份,再將鍵值與中間值比較,如鍵值相等則找到,
小於再比前半段,大於再比後半段。如此,分段比較至找到或無資料為止
優點:搜尋效率佳,平均次數 = log2 N
缺點
資料必需事先排序
檔案資料必需使是可直接存取或隨機檔
資料搜尋 3/4
15
16. Make
each
day
count
void binary_search(){
int data[] = {1, 3, 4, 6, 7, 8, 9, 12, 15};
int i, n, fnum, high, low, middle;
n = sizeof(data) / sizeof(data[0]);
low = 0, high = n;
middle = (low + high) / 2; //搜尋中間位
printf("n輸入欲搜尋的整數:");
scanf("%d", &fnum);
do {
if (data[middle] == fnum) { //找到資料
printf("n%d在陣列元素data[%d]內", fnum, middle);
break;
}
else if (fnum < data[middle])
high = middle - 1; //搜尋左半部
else low = middle + 1; //搜尋右半部
middle = (low + high) / 2; //更新中間位置
} while(low <= high);
if (low > high) printf("n%d資料不在陣列中", fnum);
}
資料搜尋 4/4
16
19. Make
each
day
count
void bubble_sort() {
int data[] = {26, 62, 2, 12, 39, 5};
int i, j, k, temp, n, flag;
n = sizeof(data) / sizeof(data[0]);
printf("未排序資料n");
for (k = 0; k < n; k++) printf("%d ", data[k]);
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; //表示發生過交換
}
}
printf("n第%d回排序結果n", i + 1);
for (k = 0; k < n; k++) printf("%d ", data[k]);
if (flag == 0) break; //此回合沒有發生交換,表示資料已排序
}
資料排序 3/17
19
25. Make
each
day
count
void select_sort() {
int data[] = {26, 62, 2, 12, 39, 5};
int i, j, k, temp, n;
n = sizeof(data) / sizeof(data[0]);
printf("未排序資料n");
for (k = 0; k < n; k++)
printf("%d ", data[k]);
for (i = 0; i < n - 1; i++){
for (j = i + 1; j < n; j++){
if (data[i] > data[j]){
temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
printf("n第%d回排序結果n", i + 1);
for (k = 0; k < n; k++)
printf("%d ", data[k]);
}
資料排序 9/17
25
27. Make
each
day
count
希爾排序法 (Shell Sorting)
泡沫排序或插入排序,可能要進行多次的比較和交換才能將該數據移至正
確位置。而希爾排序會用較大的步⻑移動數據,所以小數據只需進行少數
比較和交換即可到正確位置
由大到小選定數個比對間距 (gap)
將資料依指定的 gap 分組,比較第 i 筆與第 i + gap 筆資料,若前者大於後
者,則交換前後資料
每⼀回合必須持續做到沒有發生資料交換 (No SWAP) 為止
調小 gap 值,重覆排序作業,直到 gap 為 1 為止
資料排序 11/17
27
37. Make
each
day
count
存取二維陣列要使用 2 個索引值
每個維度索引值從 0 開始
任⼀維度最大索引值為為元素數 - 1
索再使用指定敘述指定二維陣列的每⼀個元素值,如下所示:
int i, sum = 0;
float average;
int quizzes[5][2] = {{74, 56}, {37, 68}, {65, 83}, {72, 68}, {75, 87}};
for (i = 0; i < 5; i++){
sum = sum + quizzes[i][0];
}
average = sum / 5.0;
存取二維陣列內容
37
46. Make
each
day
count
char[] strncat(char[] s1, char[] s2, int n)
將字串 s2 前⾯ n 個字元串接到字串 s1 之後,傳回 s1。注意:s1⻑度必須
能容納原來的s1字串加上s2字串
char msg1[20] = "hello";
char msg2[20] = "welcome";
strncat(msg1, msg2, 3); //msg1內容為"hellowel"
標準函數庫的字串函數 3/9
46
47. Make
each
day
count
char *strchr(char[] str, char ch);
回傳 str 字串中第⼀次出現 ch 字元之位置開始字串,搜尋失敗傳回NULL
char msg[30] = "make each day count";
char *ptr, ch = 'c';
ptr = strchr(msg, ch);
printf("make each day countn");
if (ptr)
printf("The character %c is at position: %dn", ch, ptr-msg);
else
printf("The character was not foundn");
標準函數庫的字串函數 4/9
47
49. Make
each
day
count
int strcmp(const char* s1, char* s2)
比較字串 s1 和 s2,當 s1 比 s2 小時傳回負值;s1 等於 s2 時傳回 0;s1 比
s2 大時傳回正值
char *msg1 = "hi", *msg2 = "hello", *msg3 = "aloha";
if (strcmp(msg2, msg1) > 0)
printf("msg2 is greater than msg1n");
else
printf("msg2 is less than msg1n");
if (strcmp(msg2, msg3) > 0)
printf("msg2 is greater than msg3n");
else
printf("msg2 is less than msg3n");
標準函數庫的字串函數 6/9
49
50. Make
each
day
count
int strncmp (char* s1, char * s2 , int n )
比較兩個字串的前 n 個字元是否相等
兩個字串相同時回傳 0,第⼀個字串大於第二個字串回傳正值,第⼀個
字串小於第二個字串回傳負值
printf("%dn", strcmp("AAA", "AAZ")); //-1
char *strrev(char[] str)
將 str 字串內容前後反轉
char *strlwr(char[] str)
將 str 字串內容轉成小寫英文字⺟
char *strupr(char[] str)
將 str 字串內容轉成大寫英文字⺟
標準函數庫的字串函數 7/9
50
51. Make
each
day
count
char *strtok(char[] str1, const char *str2);
依據 str2 中的分隔字元,將 str1 分割成字符。str1 中出現 str2 的分隔字元
處,會置換為0字元。 在第⼀次呼叫strtok()時,必需給 str1 字串, 以後
再呼叫時,參數str1設成NULL即可。 每次呼叫成功則傳回下⼀個分割後
的字串指標,無法分割時傳回NULL
const char str[80] = "This is - www.gitbook.net - website";
const char *delimit = " -.";
char *token;
/* get the first token */
token = strtok(str, delimit);
/* walk through other tokens */
while (token != NULL) {
printf("%sn", token);
token = strtok(NULL, delimit);
}
標準函數庫的字串函數 8/9
51
52. Make
each
day
count
int strxfrm (char* s1, char * s2 , int n )
以 s2 前 n 個字元取代 s1 前 n 個字元
char *strstr(char[] str1, char[] str2);
回傳 str1 字串中第⼀次出現 str2 字串之位置開始字串,搜尋失敗傳回
NULL
char s[] = "Self-trust is the first secret of success.";
char t[] = "secret";
char *test;
test = strstr(s, t);
printf("%sn", test); //secret of success.
標準函數庫的字串函數 9/9
52
54. Make
each
day
count
資料變數宣告
int i;
char number[9];
char special[9] = "96363025"; //特別獎號碼
char grand[9] = "69095110"; //特獎號碼
char first[3][9] = {"96745865", "98829035", "45984442"}; //頭獎號碼
char additional_sixth[3][4] = {"292", "650", "230"}; //增開六獎號碼
while(1) {
printf("請輸入發票號碼:n");
gets(number);
if (number[0]=='0') break;
...
}
Lab 統一發票對獎程式 1/5
54
55. Make
each
day
count
if (strcmp(number, special) == 0) {
printf("恭喜你中了特別獎!金額為1000萬元!n");
continue;
}
if (strcmp(number, grand) == 0) {
printf("恭喜你中了特獎!金額為200萬元!n");
continue;
}
for (i = 0; i < 3; i++) {
if (strcmp(number, first[i])==0) {
printf("恭喜你中了頭獎!金額為20萬元!n");
break;
}
}
if (i < 3) continue;
Lab 統一發票對獎程式 2/5
55
56. Make
each
day
count
for (i = 0; i < 3; i++) {
if (strncmp(&number[1], first[i] + 1, 7) == 0) {
printf("恭喜你中了二獎!金額為40000元!n");
break;
}
}
if (i < 3) continue;
for (i = 0; i < 3; i++) {
if (strncmp(&number[2], first[i] + 2, 6) == 0) {
printf("恭喜你中了三獎!金額為10000元!n");
break;
}
}
if (i < 3) continue;
Lab 統一發票對獎程式 3/5
56
9 6 7 4 5 8 6 5
first[0]
first[0]+1
9 6 7 4 5 8 6 5
first[0]
first[0]+2
7
6
9 8 7 6 5 8 6 5
number
&number[1]
7
9 8 7 6 5 8 6 5
number
&number[2]
6
57. Make
each
day
count
for (i = 0; i < 3; i++) {
if (strncmp(&number[3], first[i] + 3, 5) == 0) {
printf("恭喜你中了四獎!金額為4000元!n");
break;
}
}
if (i < 3) continue;
for (i = 0; i < 3; i++) {
if (strncmp(&number[4], first[i] + 4, 4) == 0) {
printf("恭喜你中了五獎!金額為1000元!n");
break;
}
}
if (i < 3) continue;
Lab 統一發票對獎程式 4/5
57
9 6 7 4 5 8 6 5
first[0]
first[0]+3
5
9 6 7 4 5 8 6 5
first[0]
first[0]+4
4
9 8 7 6 5 8 6 5
number
&number[3]
5
9 8 7 6 5 8 6 5
number
&number[4]
4
58. Make
each
day
count
我們在程式中宣告的每⼀個變數,系統都會在記憶體中安排⼀塊適當
大小的區塊,每個記憶體區塊都有獨⼀無二的位址
⼀般變數告
datatype var_name;
指標變數宣告
指標變數內容是記憶體位址 (其它變數的位址)
datatype *var_name;
int a = 100;
int *ptr_a = &a;
printf("%#Xn", a); //0X64
printf("%#Xn", &a); //視系統而定
printf("%#Xn", ptr_a); //同&a值
printf("%#Xn", *ptr_a); //0X64
printf("%#Xn", &ptr_a); //視系統而定
指標運算子* 1/2
59
100
.
.
.
&a
a
ptr_a
&a
&ptr_a
&a+4
59. Make
each
day
count
指標的加法與減法與⼀般數值的加減法不同,在指標運算上加 1 ,是
表示前進⼀個資料型態的記憶體⻑度
int a = 100;
int *ptr_a = &a;
printf("%#Xn", &a); //視系統而定
printf("%#Xn", ptr_a); //同&a
printf("%#Xn", ptr_a+1); //同&a+4
指標變數如果沒有指定初始值,則指標變數所指的記憶體位址是未知
的,貿然使用指標變數存取資料的話,可能會造成不可預期的錯誤。
因此,如果在指標變數宣告時不同時設初始值,最好將指標設為
NULL 方便識別
int *ptr_a = NULL;
指標運算子* 2/2
60
100
.
.
.
&a
a
ptr_a
&a
&ptr_a
&a+4 = ptr_a+1
62. Make
each
day
count
⼀維陣列
dataType *varName = (dataType *)malloc(n * sizeof(dataType));
int player;
printf("玩家人數:");
scanf("%d", &player);
_Bool *flush = (_Bool *)malloc(player * sizeof(_Bool));
動態配置陣列 1/2
63
_Bool
_Bool
.
.
.
_Bool
player
flush
63. Make
each
day
count
二維陣列
dataType **varName, *pData;
varName = (dataType **)malloc(m * sizeof(datatype *) + m*n*sizeof(dataType));
for (i = 0, pData = (int *)(varName + m); i < m; i++, pData += n)
varName[i] = pData;
int player;
printf("玩家人數:");
scanf("%d", &player);
//動態建立card[player][5],用來記錄玩家的撲克牌
card = (int **)malloc(player * sizeof(int *) + player * 5 * sizeof(int));
for (i = 0, pData = (int *)(card + player); i < player; i++, pData += 5)
card[i] = pData;
動態配置陣列 2/2
64
int *
int *
.
.
.
int *
player
card int int int int int
int int int int int
int int int int int
int int int int int
65. Make
each
day
count
宣告變數
_Bool *flush;
_Bool *straight;
int **rank;
int **count;
void poker_game(){
int pack[52], i, j, k, tmp, rnd;
int suit;
int player;
int *pData;
int **card;
...
}
Lab 撲克牌梭哈(show hand)遊戲 2/11
66
67. Make
each
day
count
show_card() 副程式,用來顯示撲克牌
void show_card(int card){
int number = card % 13;
printf("%s", (card < 13)? "黑桃" : (card<26)? "紅心" : (card<39)? "方塊" : "梅花");
switch(number){
case 0: printf("A ");
break;
case 1 ... 9:
printf("%d ", number + 1);
break;
case 10:printf("J ");
break;
case 11:printf("Q ");
break;
case 12:printf("K ");
break;
}
}
Lab 撲克牌梭哈(show hand)遊戲 4/11
68
68. Make
each
day
count
發牌
//建立card[player][5],用來記錄玩家的撲克牌
card = (int **)malloc(player * sizeof(int *) + player * 5 * sizeof(int));
for(i = 0, pData = (int *)(card + player); i < player; i++, pData += 5)
card[i] = pData;
//每位玩家發5張牌牌
for(i = 0, k = 0; i < 5; i++)
for(j = 0; j < player; j++, k++)
card[j][i] = pack[k];
Lab 撲克牌梭哈(show hand)遊戲 5/11
69
int *
int *
.
.
.
int *
player
card int int int int int
int int int int int
int int int int int
int int int int int
69. Make
each
day
count
統計玩家手牌
//建立rank[player][14],用來統計玩家各點數撲克牌之張數,ACE牌可算1或14
rank = (int **)malloc(player * sizeof(int *) + player * 14 * sizeof(int));
for(i = 0, pData = (int *)(rank + player); i < player; i++, pData += 14)
rank[i] = pData;
//設定初始值
for(i = 0; i < player; i++)
for (j = 0; j < 5; j++)
rank[i][j] = 0;
//統計各點數撲克牌之張數
for(i = 0; i < player; i++){
for(j = 0; j < 5; j++)
rank[i][card[i][j] % 13]++;
rank[i][13] = rank[i][0]; //ACE牌也可當14點
}
Lab 撲克牌梭哈(show hand)遊戲 6/11
70
int *
int *
.
.
.
int *
player
rank int int ... int
int int ... int
int int ... int
int int ... int
14
70. Make
each
day
count
檢查同花
//建立flush[player],用來記錄玩家的撲克牌是否為同花
flush=(_Bool *)malloc(player * sizeof(_Bool));
//設定初始值
for(i = 0; i < player; i++) flush[i] = 0;
//檢查玩家5張牌是否相同花⾊
for(i = 0; i < player; i++){
suit = card[i][0] / 13;
flush[i] = (card[i][1]/13 == suit) && (card[i][2]/13 == suit) &&
(card[i][3]/13 == suit) && (card[i][4]/13 == suit);
}
Lab 撲克牌梭哈(show hand)遊戲 7/11
71
int *
int *
.
.
.
int *
player
card int int int int int
int int int int int
int int int int int
int int int int int
_Bool _Bool ... _Bool
player
flush
71. Make
each
day
count
檢查順⼦
//建立straight[player],用來記錄玩家的撲克牌是否為順⼦
straight = (_Bool *)malloc(player * sizeof(_Bool));
//設定初始值
for(i = 0; i < player; i++) straight[i] = 0;
//檢查玩家5張牌是否連續
for(i = 0; i < player; i++){
for(j = 0; j < 10; j++){
if(rank[i][j] == 0) continue;
for(k = 1; k < 5; k++)
if(rank[i][j + k] == 0) break;
if(k == 5){
straight[i] = 1;
break;
}
}
}
Lab 撲克牌梭哈(show hand)遊戲 7/11
72
int *
int *
.
.
.
int *
player
rank int int ... int
int int ... int
int int ... int
int int ... int
14
_Bool _Bool ... _Bool
player
straight
72. Make
each
day
count
統計玩家牌型組合
//動態建立count[player][5]用來統計玩家撲克牌中之同點數牌情形
count = (int **)malloc(player * sizeof(int *) + player * 5 * sizeof(int));
for(i=0, pData = (int *)(count + player); i < player; i++, pData += 5)
count[i] = pData;
//設定初始值
for(i = 0; i < player; i++)
for (j = 0; j < 5; j++) count[i][j] = 0;
//count[2]==1 對⼦;count[2]==2 兩對;count[3]==1 三條;count[4]==1 鐵支
for(i = 0; i < player; i++) {
for(j = 0; j < 13; j++)
count[i][rank[i][j]]++;
}
Lab 撲克牌梭哈(show hand)遊戲 8/11
73
int *
int *
.
.
.
int *
player
count int int int int int
int int int int int
int int int int int
int int int int int
73. Make
each
day
count
梭哈
for(i = 0; i < player; i++){
printf("第%d位玩家:", i + 1);
for(j = 0; j < 5; j++){ //顯示玩家手牌
show_card(card[i][j]);
}
printf("n梭哈牌型:");
show_hand(i);
printf("nn");
}
Lab 撲克牌梭哈(show hand)遊戲 9/11
74