---
# System prepended metadata

title: Quiz 11
tags: [程設一quiz]

---

Quiz 11
===
# Index
1. [總說明](#%E7%B8%BD%E8%AA%AA%E6%98%8E)
    - [`main()`](#main-line-1--line-25)
    - [`sort()`](#main-line-1--line-25)
    - [`weight()`](#weightchar-c-line-79--line-85)
2. [[A] Bubble Sort](#A-Bubble-Sort)
    - [Explanation](#Explanation)
    - [Code](#Code)
3. [[B] Selection Sort]()
    - [Explanation](#Explanation1)
    - [Code](#Code1)
4. [[C] Insertion Sort]()
    - [Explanation](#Explanation2)
    - [Code](#Code2)


# 總說明
這週三題的解法相差無幾，差別僅在於演算法而已，因此會先在這裡一次說明他們的做法。
以下將以[[B] Selection Sort](https://hackmd.io/gvmuZuSMSlSeTEsvD5h2Lg#B-Selection-Sort)做範例說明。

### `main()` (line 1 ~ line 25)
1. 首先先建立一個字元陣列，其長度（在此為`SIZE` = 60）隨意，只要能存入所有輸入的字元即可。
2. 欲將使用者輸入的字串存入陣列中的方法有許多種，`scanf`（需一個一個字元慢慢讀取，無法一次讀取完整的含有空白的字串）, `gets`, `fgets`等等，因使用`gets`有時會有warning，因此在此我選則使用`fgets`。
    `gets`及`fgets`有點類似，當未有任何字串被輸入，將會回傳NULL，所以若想讓程式執行直到輸入EOF，直接寫`while(gets(string))`即可。
     - `gets(string)`
     - `fgets(string, string_length, FILE)`
        - 讀取鍵盤的輸入時，將FILE設為stdin

3. 為了符合題目所要求的輸出規則（每組不同input之間需有一行空白，而最後一次輸出後則無一行空白），需另外設立一個變數(在此為`printed`)來判斷此次input是否為第一次，若為第一次，則不需留空，若是，則輸出一行空白行。

4. 呼叫函式，排序及輸出等等的皆會在函式中進行。

5. 結束以上工作後，再進行下一輪前需要先將陣列初始化，避免上一次所輸入的字串較下一次的長，使得一些上次所存的字元仍留在字串中，被誤認為是新輸入的字串內容。
    - 可使用`for` loop將字元陣列裡的每一格皆設定為一個非使用者會輸入的值(e.g. 空白， , ，& 等等)
    - 在此使用動態陣列calloc
        - calloc會將每格皆初始化為0
        - [動態陣列說明](https://openhome.cc/Gossip/CGossip/MallocFree.html)

### `sort(char arr[])` (line 27 ~ line 77)
sort()可簡單為以下執行事項
1. 建立一個新字元陣列，其中只留下我們需要的字元
2. 輸出(`pass`)
3. 排序

說明：
1. 新字元陣列
    - 此陣列的長度隨意，只要能夠儲存每一項即可
    - 使用for loop，並判段`arr`（原陣列）裡的每個字元是否為所求，若是，則將它存入`new_arr`（新陣列）之中。
    - 在將各個字元存入新陣列的同時，需同時紀錄新陣列所儲存的項目數，這將在之後的排序及輸出用到
    - [A]題因為有負數的關係，因此新陣列的變數型態需設為`int`，才有辦法儲存負數，其餘字元將以ascii 表中所對應到的數值儲存。
    - 註：B, C題中在字元陣列的尾端加上`\0`僅僅是為了方便測試，此行非必要
2. 輸出
    - 此三題皆會用到兩層迴圈，而輸出的部分需放在外層迴圈內。
4. 排序
    - 詳見各題


### `weight(char c)` (line 79 ~ line 85)
因為B, C題須依照題目所規定的大小優先順序排列，因此需另外使用一個陣列（在此為`w_arr` (line 8)）儲存它們所對應到的大小，並使用此函式以得到各個字元的數值。
此函式將會利用for loop在`w_arr`中尋找與parameter `c`相同的字元，若找到了，將會回傳字元在`w_arr`的index，其index即為它的大小、先後順序。

# [A] Bubble Sort
## Explanation
Bubble Sort動畫說明：https://www.youtube.com/watch?v=nmhjrI-aW5o
## Code
```c=
#include <stdio.h>
#include <stdlib.h>
#define SIZE 60

void bubble_sort(char arr[]);

int main(){
    char *input = calloc(SIZE, sizeof(char));
    int printed = 0;
    
    while(fgets(input, SIZE, stdin)){
        if(printed){
            puts("");
        }
        else{
            printed = 1;
        }

        bubble_sort(input);

        free(input);
        input = calloc(SIZE, sizeof(char));
    }
}

void bubble_sort(char arr[]){
    //create new array without spaces and other useless char
    int *new_arr = malloc(SIZE * sizeof(int));
    int len = 0;
    int negative = 0;

    int swapped;
    int tmp;
    for(int i=0; i<SIZE; i++){
        if(((arr[i] >= 'a') && (arr[i] <= 'z')) || ((arr[i] >= 'A') && (arr[i] <= 'Z'))){
            new_arr[len++] = arr[i];
        }
        else if((arr[i] >= '0') && (arr[i] <= '9')){
            new_arr[len++] = arr[i];
            if(negative){
                new_arr[len-1] *= (-1);
                negative = 0;
            }
        }
        else if(arr[i] == '-'){
            negative = 1;
        }
    }

    for(int i=0; i<len; i++){
        //print
        printf("Pass %d:", i);
        for(size_t idx=0; idx<len; idx++){
            if(new_arr[idx] < 0){
                printf(" -%c", new_arr[idx]*(-1));
            }
            else{
                printf(" %c", new_arr[idx]);
            }

            if(idx == (len-i-1)){
                printf(" /");
            }
        }
        puts("");

        //sort, swap
        swapped = 0;
        for(int j=1; j<len-i; j++){
            if(new_arr[j] < new_arr[j-1]){
                tmp = new_arr[j];
                new_arr[j] = new_arr[j-1];
                new_arr[j-1] = tmp;
                swapped = 1;
            }
        }

        if(!swapped){
            break;
        }
    }
}
```

# [B] Selection Sort
## Explanation
Selection Sort動畫說明：https://www.youtube.com/watch?v=xWBP4lzkoyM
## Code
```c=
#include <stdio.h>
#include <stdlib.h>
#define SIZE 60

void selection_sort(char arr[]);
size_t weight(char c);

char w_arr[22] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F'};

int main(){
    char *input = calloc(SIZE, sizeof(char));
    int printed = 0;

    while(fgets(input, SIZE, stdin)){
        if(printed){
            puts("");
        }
        else{
            printed = 1;
        }
        selection_sort(input);
        free(input);
        input = calloc(SIZE, sizeof(char));
    }
}

void selection_sort(char arr[]){
    //create new array without spaces and other useless char
    char *new_arr = malloc(SIZE * sizeof(char));
    int len = 0;
    for(int i=0; i<SIZE; i++){
        if(((arr[i] >= '0') && (arr[i] <= '9')) || ((arr[i] >= 'a') && (arr[i] <= 'f')) || ((arr[i] >= 'A') && (arr[i] <= 'F'))){
            new_arr[len++] = arr[i];
        }
    }
    new_arr[len] = '\0';

    size_t smallest_idx;
    size_t smallest_w, curr_w;
    char tmp;

    //sorting
    for(int pass=0; pass<len; pass++){
        //print
        printf("Pass %d:", pass);
        for(size_t i=0; i<len; i++){
            if(i == pass){
                printf(" /");
            }

            printf(" %c", new_arr[i]);
        }
        puts("");

        if(pass == len-1){
            break;
        }
        
        //find smallest
        smallest_idx = pass;
        smallest_w = weight(new_arr[smallest_idx]);
        for(size_t curr=pass+1; curr<len; curr++){
            curr_w = weight(new_arr[curr]);
            if(curr_w < smallest_w){
                smallest_idx = curr;
                smallest_w = curr_w;
            }
        }

        //swap
        tmp = new_arr[pass];
        new_arr[pass] = new_arr[smallest_idx];
        new_arr[smallest_idx] = tmp;
    }

    free(new_arr);
}

size_t weight(char c){
    for(int i=0; i<22; i++){
        if(c == w_arr[i]){
            return i;
        }
    }
}
```

# [C] Insertion Sort
## Explanation
Insertion Sort 動畫說明：https://www.youtube.com/watch?v=OGzPmgsI-pQ
## Code
```c=
#include <stdio.h>
#include <stdlib.h>
#define SIZE 60

void insertion_sort(char arr[]);
size_t weight(char c);

char w_arr[14] = {'2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'};

int main(){
    char *input = calloc(SIZE, sizeof(char));
    int printed = 0;

    while(fgets(input, SIZE, stdin)){
        if(printed){
            puts("");
        }
        else{
            printed = 1;
        }
        insertion_sort(input);
        free(input);
        input = calloc(SIZE, sizeof(char));
    }
}

void insertion_sort(char arr[]){
    //create new array without spaces and other useless char
    char *new_arr = malloc(SIZE * sizeof(char));
    int len = 0;
    for(int i=0; i<SIZE; i++){
        if(((arr[i] >= '0') && (arr[i] <= '9')) || ((arr[i] >= 'a') && (arr[i] <= 'z')) || ((arr[i] >= 'A') && (arr[i] <= 'Z'))){
            new_arr[len++] = arr[i];
        }
    }
    new_arr[len] = '\0';

    size_t key_w;
    size_t k, ptr;
    char key;

    //sorting
    for(int pass=0; pass<len; pass++){
        //print
        printf("Pass %d:", pass);
        for(int i=0; i<len; i++){
            printf(" %c", new_arr[i]);
            if(i == pass){
                printf(" /");
            }
        }
        puts("");

        if(pass == len-1){
            break;
        }

        //swap
        k = pass+1;
        key = new_arr[k];
        key_w = weight(key);
        ptr = k;
        while((ptr >= 1) && (weight(new_arr[ptr-1]) > key_w)){
            new_arr[ptr] = new_arr[ptr-1];
            ptr--;
        }
        new_arr[ptr] = key;
    }

    free(new_arr);
}

size_t weight(char c){
    for(int i=0; i<14; i++){
        if(c == w_arr[i]){
            return i;
        }
    }
}
```

###### tags: `程設一quiz`