{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Week14.ipynb","provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyMzeRpy4PtC/feRJan0aL+9"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["#第十四週上課內容"],"metadata":{"id":"9xoK4OIjIfZA"}},{"cell_type":"markdown","source":["###GitHub 教材參考資料\n","\n","[https://github.com/htchen/i2p-nthu/tree/master/程式設計一/更多關於指標的用法](https://github.com/htchen/i2p-nthu/tree/master/%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88%E4%B8%80/Supplementary%20Material%201)\n","\n"],"metadata":{"id":"05G1Fqg6GRZX"}},{"cell_type":"markdown","source":["## 第十三週還沒講完的內容\n"],"metadata":{"id":"mviKuWaapY32"}},{"cell_type":"code","source":["%%writefile E13_03.c\n","#include <stdio.h>\n","#define MAX_SIZE 50000\n","#define LOWER_LIMIT 0\n","#define UPPER_LIMIT 1000000\n","int main(int argc, char * argv[]) {\n","  int data[MAX_SIZE];\n","  int i, j, size, k;\n","  int maxval = LOWER_LIMIT, minval = UPPER_LIMIT;\n","  \n","  FILE * fin;\n","  fin = fopen(argv[1], \"rt\");\n","  for (i=0; i<argc; ++i) {\n","    printf(\"The %dth argument is %s\\n\", i, argv[i]);\n","  }\n","\n","  fscanf(fin, \"%d\", &size);\n","  for (k = 0; k < size; k++) {\n","    if (fscanf(fin, \"%d\", &data[k]) != 1)\n","      break;\n","  }\n","  for (i = 0, j = size - 1; i <= j; i++, j--) {\n","    if (data[i] < data[j]) {\n","      if (minval > data[i])\n","        minval = data[i];\n","      if (maxval < data[j])\n","        maxval = data[j];\n","    } else {\n","      if (maxval < data[i])\n","        maxval = data[i];\n","      if (minval > data[j])\n","        minval = data[j];\n","    }\n","  }\n","  printf(\"%d %d\\n\", minval, maxval);\n","\n","  return 0;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"4mllPj9Rt8qF","executionInfo":{"status":"ok","timestamp":1652183959898,"user_tz":-480,"elapsed":318,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"33fab8e0-9458-4f2c-a2ed-f9a81abffacd"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E13_03.c\n"]}]},{"cell_type":"code","source":["%%shell\n","\n","gcc E13_03.c -o E13_03\n","if test -f \"data_50000.txt\"; then\n","  ./E13_03 data_50000.txt -o Hello\n","else\n","  pip install gdown\n","  gdown https://drive.google.com/uc?id=1XapeYR19tJaP5mrxQA8RkfWZdIBouKfc\n","  gdown https://drive.google.com/uc?id=1yI6-IajsjRMH_bSOVdvs1e1oSdo9rFfy\n","fi"],"metadata":{"id":"3yZlwmmjsiKP","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652183963086,"user_tz":-480,"elapsed":301,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"8329a7f1-3ca5-46a5-eda1-71ba76e1a33e"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The 0th argument is ./E13_03\n","The 1th argument is data_50000.txt\n","The 2th argument is -o\n","The 3th argument is Hello\n","0 49999\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":123}]},{"cell_type":"markdown","source":["## Example 5\n","###**指標和二維陣列**\n","\n","關於二維陣列，我們可以再結合已經學到的指標概念，對它做更進一步的運用。假設我們宣告了一個二維陣列：\n","```\n","int z[4][2] = {{1,2}, {3,4}, {5,6}, {7,8}};\n","```\n","則 `z` 本身是一個陣列，總共有四個元素，而其中的每個元素本身也都是一個「包含了兩個元素的陣列」。由於 `z` 可以代表陣列第一個元素的位址，所以 `z` 的值和 `&z[0]` 是一樣的。而又由於 `z[0]` 本身也是個陣列 (包含兩個整數)，所以 `z[0]` 同時也代表著它的第一個元素的位址，也就是 `&z[0][0]`。對於二維陣列來說，`z` 所代表的位址，和 `z[0]` 代表的位址是一樣的，都是整個二維陣列最前面的那個整數元素的位址。\n","\n","雖然 `z` 所代表的位址和 `z[0]` 代表的位址一樣，但是由於 `z` 和 `z[0]` 是不同型別的指標，所以對他們做位址加一的動作，不論是在意義上或是造成的效果，都不相同。如果計算 `z+1`，在這個例子裡得到的位址變化是增加八個 bytes，也就是兩個整數的大小。如果計算 `z[0]+1`，則位址變化則只會增加 4 bytes。因為意義上 `z+1` 相當於是 `&z[1]`，而 `z[0]+1` 則相當於 `&z[0][1]`。\n","\n","接下來看看關於取出記憶體位址裡儲存的值的寫法。首先由於 `z[0]` 是 `z[0][0]` 這個元素的位址 (`z[0]` 和 `&z[0][0]` 是一樣的)，所以 `*(z[0])` 等於是 `*&z[0][0]` 也就等於是 `z[0][0]` 這個元素的值。而又由於 `z` 代表的位址等於 `&z[0]`，所以 `*z` 就等於是 `z[0]`，再套用前面的結果就得到 `*(*z)` 等於是 `*(z[0])` 等於是 `*&z[0][0]`，所以也就是 `z[0][0]`。\n","\n","以上所有的動作可以用下面的範例來測試一次。"],"metadata":{"id":"rUct0XJLrE1w"}},{"cell_type":"code","source":["%%writefile E13_05.c\n","#include <stdio.h>\n","int main(void)\n","{\n","   int z[4]   [2] = {{1,2}, {3,4}, {5,6}, {7,8}};\n","   \n","/*\n"," a[i] ⟺ *(a+i)\n","&a[i] ⟺ (a+i)\n"," */\n","   printf(\"       z: %p\\n\", z);\n","   printf(\"   &z[0]: %p\\n\", &z[0]); // &z[0] => z+0 => z\n","   printf(\"    z[0]: %p\\n\", z[0]);  // (z[0]+0) => & z[0][0]\n","   printf(\"&z[0][0]: %p\\n\", &z[0][0]); \n","   printf(\" z[0][0]: %d\\n\", z[0][0]);\n","   printf(\"\\n\"); \n","   printf(\"     z+1: %p\\n\", z+1); \n","   printf(\"   &z[1]: %p\\n\", &z[1]); // &z[1] => z+1\n","   printf(\"  z[0]+1: %p\\n\", z[0]+1); // (z[0]+1) => &z[0][1]\n","   printf(\"&z[0][1]: %p\\n\", &z[0][1]); // address of 2\n","   printf(\"\\n\"); \n","   printf(\"      *z: %p\\n\", *z);  // *z => *(z+0) => z[0] => &z[0][0]\n","   printf(\"    z[0]: %p\\n\", z[0]); // z[0] => &z[0][0]\n","   printf(\"   *z[0]: %d\\n\", *z[0]); // *z[0] => *(z[0] + 0) => z[0][0]\n","   printf(\" z[0][0]: %d\\n\", z[0][0]); \n","   printf(\"     **z: %d\\n\", **z); // **z => * *(z+0) => * z[0] => z[0][0]\n","   \n","   return 0; \n","}"],"metadata":{"id":"CUD4U1iTuWSa","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652186315631,"user_tz":-480,"elapsed":307,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"fb5c0d3f-a76d-49ab-a4e9-8e65c61bcdca"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E13_05.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E13_05.c -o E13_05\n","./E13_05"],"metadata":{"id":"dn61T8gVudiD","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652186327039,"user_tz":-480,"elapsed":325,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"2ddc9a42-f38d-41eb-d406-e4f262b40d47"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["       z: 0x7ffcf7736bb0\n","   &z[0]: 0x7ffcf7736bb0\n","    z[0]: 0x7ffcf7736bb0\n","&z[0][0]: 0x7ffcf7736bb0\n"," z[0][0]: 1\n","\n","     z+1: 0x7ffcf7736bb8\n","   &z[1]: 0x7ffcf7736bb8\n","  z[0]+1: 0x7ffcf7736bb4\n","&z[0][1]: 0x7ffcf7736bb4\n","\n","      *z: 0x7ffcf7736bb0\n","    z[0]: 0x7ffcf7736bb0\n","   *z[0]: 1\n"," z[0][0]: 1\n","     **z: 1\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":127}]},{"cell_type":"markdown","source":["接著就來看看如何宣告一個可以指向二維陣列的指標。用上一個程式為例，`z` 是一個二維陣列，也代表一個「包含兩個整數元素的陣列」的位址，所以我們可以宣告一個指向「包含兩個整數元素的陣列」的指標，用來儲存這個陣列的位址，宣告的方式是\n","```\n","int (*pz)[2];  \n","```\n","這樣宣告的意思是說， `pz` 是一個指到整數陣列的指標，而牠所指到的陣列包含了兩個整數元素。要注意上面的括號一定要加，因為如果不加的話，代表的是另一種意義：\n","```\n","int *py[3];\n","```\n","這種宣告方式是表示 `py` 是一個「有三個元素的陣列」，其中每個元素都是「指向整數的指標」，或者是說，每個元素都記錄著某個記憶體位址。有了對應到二維陣列的指標之後，我們就可以把這個指標指向二維陣列，例如\n","```\n","pz = z;\n","```\n","然後就可以把 `pz` 這個指標當作二維陣列來使用，所以 `pz[2][1]` 就相當於是 `z[2][1]`。\n"],"metadata":{"id":"8k-L-Ss6sEa4"}},{"cell_type":"code","source":["%%writefile test.c\n","#include <stdio.h>\n","\n","typedef char Char3 [3];\n","\n","void f(char (*w) [3], int row, int col) {\n","   printf(\"%c\\n\", w[row][col]); \n","}\n","int main(void)\n","{\n","  char v[4][3] = {{'A', 'B', 'C'}, {'D', 'E', 'F'}, {'G', 'H', 'I'},\n","                {'J', 'K', 'L'}};\n","  f(v, 3, 1);\n"," \n","\n","  return 0;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"9qGmVTd-DNDR","executionInfo":{"status":"ok","timestamp":1652786074582,"user_tz":-480,"elapsed":585,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"4a2868e5-b329-4d84-c6ad-0001add7fffb"},"execution_count":10,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting test.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc test.c -o test\n","./test"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Kr702DbBF42D","executionInfo":{"status":"ok","timestamp":1652786079683,"user_tz":-480,"elapsed":394,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"e2ceee9f-c70b-4dd7-b879-7896fbe8e9b8"},"execution_count":11,"outputs":[{"output_type":"stream","name":"stdout","text":["K\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":11}]},{"cell_type":"markdown","source":["# Exercise 1\n","\n","根據變數的宣告\n","```\n","int * pt;\n","int (*pa)[3];\n","int a[2][3];\n","int b[3][2];\n","int*   *p2;\n","```\n","來判斷下列動作是否合法:\n","```\n","pt = &a[0][0]; \n","pt = a[0];\n","pa = a; \n","pa = b;\n","p2 = &pt;\n","*p2 = b[0];\n","p2 = b;\n","```"],"metadata":{"id":"7zvidNTJtv9p"}},{"cell_type":"code","source":["%%writefile W13_01.c\n","#include <stdio.h>\n","\n","int main()\n","{\n","  int *pt;\n","  int (*pa)[3];\n","  int a[2][3];\n","  int b[3][2];\n","  int **p2;\n","\n","  pt = &a[0][0];\n","  pt = a[0];\n","  pa = a; \n","  pa = b;\n","  p2 = &pt;\n","  *p2 = b[0];\n","  p2 = b;\n","  return 0;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"-4dGxug7vapd","executionInfo":{"status":"ok","timestamp":1652786651870,"user_tz":-480,"elapsed":563,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"f8a88cc6-1dd6-4d38-e67e-35f4f3ba5308"},"execution_count":12,"outputs":[{"output_type":"stream","name":"stdout","text":["Writing W13_01.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc W13_01.c -o W13_01\n","./W13_01"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"s4HVR61NvjWu","executionInfo":{"status":"ok","timestamp":1652786672491,"user_tz":-480,"elapsed":490,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"71077545-9c78-48db-c806-d05b19b8726d"},"execution_count":14,"outputs":[{"output_type":"stream","name":"stdout","text":["\u001b[01m\u001b[KW13_01.c:\u001b[m\u001b[K In function ‘\u001b[01m\u001b[Kmain\u001b[m\u001b[K’:\n","\u001b[01m\u001b[KW13_01.c:14:6:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kassignment from incompatible pointer type [\u001b[01;35m\u001b[K-Wincompatible-pointer-types\u001b[m\u001b[K]\n","   pa \u001b[01;35m\u001b[K=\u001b[m\u001b[K b;\n","      \u001b[01;35m\u001b[K^\u001b[m\u001b[K\n","\u001b[01m\u001b[KW13_01.c:17:6:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kassignment from incompatible pointer type [\u001b[01;35m\u001b[K-Wincompatible-pointer-types\u001b[m\u001b[K]\n","   p2 \u001b[01;35m\u001b[K=\u001b[m\u001b[K b;\n","      \u001b[01;35m\u001b[K^\u001b[m\u001b[K\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":14}]},{"cell_type":"markdown","source":["# Example 6\n","\n","## 如何傳二維陣列給 function\n","\n","要把二維陣列傳給某個 function，必須要使用上面的範例裡的 function 宣告方式。由於一個二維陣列可以解讀成「由一維陣列組成的一維陣列」，但是傳遞參數時，我們能夠做的事情只是把位址 (某個大小為 4 bytes 的值) 傳給 functions，所以傳遞二維陣列其實應該是要傳遞位址給某個指標變數。那麼這個接收二維陣列的指標變數該宣告成什麼樣子呢？依照我們前面討論的指標型別，我們知道 `int (*ap)[COLS]` 這樣的指標，和 `int arr2[ROWS][COLS]` 二維陣列具有同樣的型別，都是一個包含 `COLS` 個元素的陣列的起始位址。所以我們把 function 宣告成 `int sum2d(int (*ap)[COLS], int rows);`，而呼叫的時候就把二維陣列的名稱傳進去就可以，例如 `sum2d(arr2, ROWS);`。要特別注意的地方是 `[COLS]` 這個東西一定要寫，因為這樣 compiler 才知道指標指到的是一個「包含了 `COLS` 個元素的整數陣列」。假如兩個指標 `pa` 和 `pb` 指到的陣列的大小不一樣，則這兩個指標的型別就不一樣，因為 `pa+1` 和 `pb+1` 的效果是不同的。"],"metadata":{"id":"RekjD2X7xkdD"}},{"cell_type":"code","source":["%%writefile E13_06.c\n","#include <stdio.h>\n","#define ROWS 3\n","#define COLS 4\n","int sum2d(int (*ap)[COLS], int rows);\n","/* int sum2d(int [][COLS], int); */\n","/* int sum2d(int a[][COLS], int rows); */\n","int main(void)\n","{\n","   int arr2[ROWS][COLS] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};\n","\n","   printf(\"Sum = %d\\n\", sum2d(arr2, ROWS));\n","   \n","   return 0; \n","}\n","int sum2d(int a[][COLS], int rows)\n","{\n","   int r, c;\n","   int total = 0;\n","\n","   for (r = 0; r < rows; r++)\n","      for (c = 0; c < COLS; c++)\n","         total += a[r][c];\n","\n","   return total;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Q1Tr_qiXyMIr","executionInfo":{"status":"ok","timestamp":1652148300768,"user_tz":-480,"elapsed":326,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"3175952c-c8b0-4b73-c685-1c158ec9781a"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Writing E13_06.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E13_06.c -o E13_06\n","./E13_06"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"wxVZ1QntzYun","executionInfo":{"status":"ok","timestamp":1652148312062,"user_tz":-480,"elapsed":324,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"d83cdb9c-e08e-48fd-93f2-84f3b8a2c834"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Sum = 78\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":54}]},{"cell_type":"markdown","source":["# Exercise 2\n","## Insertion Sort\n","\n","https://en.wikipedia.org/wiki/Insertion_sort\n","```\n","i ← 1\n","while i < length(A)\n","    j ← i\n","    while j > 0 and A[j-1] > A[j]\n","        swap A[j] and A[j-1]\n","        j ← j - 1\n","    end while\n","    i ← i + 1\n","end while\n","```\n","把上面的演算法 pseudo code，翻譯成 C 語言："],"metadata":{"id":"Jyb6tF6fu_MK"}},{"cell_type":"code","source":["%%writefile W13_02.c\n","#include <stdio.h>\n","void insertion(int *p, int size)\n","{\n","  int i = 1, j, tmp;\n","  while (i < size) {\n","    j = i;\n","    while (j > 0 && p[j-1] > p[j]) {\n","        tmp = p[j];\n","        p[j] = p[j-1];\n","        p[j-1] = tmp;\n","        --j;\n","    }\n","    ++i;\n","  }\n","}\n","\n","void show(int *p, int size)\n","{\n","    int i;\n","    for (i=0; i<size; ++i) {\n","        printf(\"%d \", p[i]);\n","    }\n","    printf(\"\\n\");\n","}\n","\n","int main(void)\n","{\n","  int data[] = {5, 8, 1, 3, 2, 9, 7};\n","  show(data, 7);\n","  insertion(data, 7);\n","  show(data, 7); \n","}"],"metadata":{"id":"D_NvYNQnvOPt","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652788486940,"user_tz":-480,"elapsed":367,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"33054498-719c-488e-dfdb-de78968cee7b"},"execution_count":25,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting W13_02.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc W13_02.c -o W13_02\n","./W13_02"],"metadata":{"id":"xSfXl-Q1vzgq","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652788496578,"user_tz":-480,"elapsed":284,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"c27bb16c-6413-4644-b22d-d28b39833dc3"},"execution_count":26,"outputs":[{"output_type":"stream","name":"stdout","text":["4\n","5 8 1 3 2 9 7 \n","1 2 3 5 7 8 9 \n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":26}]},{"cell_type":"markdown","source":["# Example 7\n","\n","## 指標、陣列、遞迴"],"metadata":{"id":"U87YB0Uk01Dt"}},{"cell_type":"code","source":["%%writefile E13_07.c\n","#include <stdio.h>\n","void permutation(char * a, int n);\n","void swap( char *, char *);\n","int main(void)\n","{\n","   char str[] = \"cats\";\n","   permutation(str, 4);\n","   return 0;\n","}\n","void permutation(char *a,  int n)\n","{\n","   int i; \n","   if (n == 1) {\n","      printf(\"%s\\n\", a);\n","   } \n","   else {\n","      for (i = 0; i < n; i++) {  \n","         swap(&a[i], &a[n-1]);   \n","         permutation(a, n-1);     \n","         swap(&a[i], &a[n-1]); \n","      }\n","   } \n","}\n","void swap(char *x, char *y)\n","{\n","   char tmp;\n","\n","   tmp = *x;\n","   *x = *y;\n","   *y = tmp;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"7mumElkp3l66","executionInfo":{"status":"ok","timestamp":1652789299906,"user_tz":-480,"elapsed":344,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"6645ead8-6f6c-4f8e-f105-3f62c6ca0b09"},"execution_count":29,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E13_07.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E13_07.c -o E13_07\n","./E13_07"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"a6hxGaQz4VTE","executionInfo":{"status":"ok","timestamp":1652789303240,"user_tz":-480,"elapsed":250,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"16138bbe-e04a-4b61-db14-2d6912b8a742"},"execution_count":30,"outputs":[{"output_type":"stream","name":"stdout","text":["atsc\n","tasc\n","tsac\n","stac\n","astc\n","satc\n","stca\n","tsca\n","tcsa\n","ctsa\n","scta\n","csta\n","asct\n","sact\n","scat\n","csat\n","acst\n","cast\n","atcs\n","tacs\n","tcas\n","ctas\n","acts\n","cats\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":30}]},{"cell_type":"markdown","source":["# 第十四週"],"metadata":{"id":"Qlgt3AfS-XSi"}},{"cell_type":"markdown","source":["## 字串處理\n","```C\n","#include <string.h>\n","```\n","\n","**`strcmp`**\n","\n","https://en.cppreference.com/w/c/string/byte/strcmp\n","\n","```C\n","int strcmp ( const char * str1, const char * str2 );\n","```\n","*Parameters*\n","> `str1` : the first string to be compared   \n","> `str2` : the second string to be compared\n","\n","*Return Value*\n",">  `< 0`  : `str1` is less than `str2`  \n",">  `> 0`  : `str2` is less than `str1`  \n",">  `== 0` : `str1` is equal to `str2`\n","\n","---\n","\n","**strcpy**\n","https://en.cppreference.com/w/c/string/byte/strcpy\n","\n","```C\n","char * strcpy ( char *restrict to, const char *restrict from );\n","```\n","\n","**strncpy**\n","https://en.cppreference.com/w/c/string/byte/strncpy\n","\n","```C\n","char * strncpy ( char *restrict to, const char *restrict from, size_t count );\n","```\n","\n","\n","**strcat**\n","https://en.cppreference.com/w/c/string/byte/strcat\n","```C\n","char *strcat( char *restrict to, const char *restrict from );\n","```\n","\n","**strncat**\n","https://en.cppreference.com/w/c/string/byte/strncat\n","```C\n","char *strncat( char *restrict to, const char *restrict from, size_t count );\n","```\n","\n","**memset** https://en.cppreference.com/w/c/string/byte/memset\n","```C\n","void *memset( void *dest, int ch, size_t count );\n","```\n","\n","**memcpy** https://en.cppreference.com/w/c/string/byte/memcpy\n","void* memcpy( void *to, const void *from, size_t count );\n","\n","\n","使用上列函數\n","\n","自己實作 `strcpy` `strcat`"],"metadata":{"id":"w3LrxO-f-bgD"}},{"cell_type":"code","source":["%%writefile E14_01.c\n","#include <stdio.h>\n","#include <string.h>\n","void Strncpy(char *to, char *from, int n) {\n","    while (*from != '\\0' && n>0) {\n","        *to = *from;\n","        to++;\n","        from++;\n","        n--;\n","    }\n","}\n","void Strncat(char *to, char *from, int n) {\n","    \n","    while(*to != '\\0') to++;\n","\n","    while (*from != '\\0' && n > 0) {\n","        *to = *from;\n","        to++;\n","        from++;\n","        n--;\n","    }\n","      \n","} \n","int main(void)\n","{\n","    char str1[] = \"abc\";\n","    char str2[10] = {0};\n","    Strncat(str2, str1, 2);\n","    Strncat(str2, str1, 2);\n","    printf(\"str1: %s\\n\", str1);\n","    printf(\"str2: %s\\n\", str2);\n"," \n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"NuchhKGVBBr1","executionInfo":{"status":"ok","timestamp":1652791334179,"user_tz":-480,"elapsed":237,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"04b4961b-2441-49e1-978c-0f20dc36c6cf"},"execution_count":77,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E14_01.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E14_01.c -o E14_01\n","./E14_01"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"8x5RBzBNBFHG","executionInfo":{"status":"ok","timestamp":1652791337946,"user_tz":-480,"elapsed":320,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"44f0c6a6-de68-4d09-9eb4-c6a6345d9d7a"},"execution_count":78,"outputs":[{"output_type":"stream","name":"stdout","text":["str1: abc\n","str2: abab\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":78}]},{"cell_type":"markdown","source":["## Example 2\n","\n","把句子以字為單位反轉\n","\n","*this is a book*\n","\n","變成\n","\n","*book a is this*\n","\n"],"metadata":{"id":"v-pgfkbDXiih"}},{"cell_type":"code","source":["%%writefile E14_02.c\n","#include <stdio.h>\n","#include <string.h>\n","\n","void reverse(char *start, char *end) {\n","    char tmp;\n","    while (start < end) {\n","        tmp = *start;\n","        *start = *end;\n","        *end = tmp;\n","        start++;\n","        end--;\n","    }\n","}\n","int main(void)\n","{\n","  char str[256];\n","  int i;\n","  char *start;\n","  fgets(str, 255, stdin);\n","  str[strlen(str)-1] = ' ';\n","  start = str;\n","  for (i=0; i<strlen(str); ++i) {\n","    if (str[i] == ' ') {\n","        reverse(start, str + i - 1);\n","        start = str + i + 1;\n","    }\n","  }\n","  reverse(str, str+strlen(str)-2);\n","  str[strlen(str)-1] = '\\0';\n","  printf(\"%s\\n\", str);\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"JCM5nQ_UazZF","executionInfo":{"status":"ok","timestamp":1652792799051,"user_tz":-480,"elapsed":251,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"d43e38ac-763e-48d8-a479-d19c9498297c"},"execution_count":103,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E14_02.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E14_02.c -o E14_02\n","./E14_02"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"KsBoHbL2audO","executionInfo":{"status":"ok","timestamp":1652792730856,"user_tz":-480,"elapsed":6195,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"75177d2c-b4f8-4b07-a4a5-b7c54d04e86c"},"execution_count":102,"outputs":[{"output_type":"stream","name":"stdout","text":["this is a book\n","book a is this\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":102}]},{"cell_type":"markdown","source":["## Example 3\n","## qsort\n","[C referecne 對於 qsort 的說明](http://en.cppreference.com/w/c/algorithm/qsort)\n","\n","\n","```C\n","void qsort( void *ptr, size_t count, size_t size, int (*comp)(const void *, const void *) )\n","```\n","\n","*   *ptr*  \n","    指向要排序的陣列的起始位置的指標\n","*   *count*  \n","    在陣列中有幾個元素要排序\n","*   *size*  \n","    在陣列中每個元素的大小，以 byte 為單位\n","*   *comp*  \n","    比較用的函數，回傳正數代表第一個參數比第二個參數小，回傳負數代表第一個參數比第二個參數大，回傳0代表兩個參數相等\n","\n","底下的程式碼示範了如何使用`qsort`ㄓ"],"metadata":{"id":"3VvMqR5g1CKX"}},{"cell_type":"code","source":["%%writefile E14_03.c\n","#include <stdio.h>\n","#include <stdlib.h>\n","#include <string.h>\n","#define SIZE 10\n","\n","int compare_int(const void *a, const void *b)\n","{\n","    const int *va = (const int *) a;\n","    const int *vb = (const int *) b;\n","    return *vb-*va;\n","}\n","\n","int compare_double(const void *a, const void *b)\n","{\n","    const double *da = (const double *) a;\n","    const double *db = (const double *) b;\n","    return (*db > *da) - (*db < *da);\n","}\n","\n","int main(void)\n","{\n","    int data1[SIZE];\n","    double data2[SIZE];\n","    int i;\n","\n","    for (i=0; i<SIZE; i++) {\n","        data1[i] = rand()%SIZE;\n","        data2[i] = (double)rand()/RAND_MAX;\n","    }\n","\n","    printf(\"original: \");\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%d \", data1[i]);\n","    }\n","    printf(\"\\n\");\n","\n","    printf(\"  sorted: \");\n","    qsort(data1, SIZE, sizeof(int), compare_int);\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%d \", data1[i]);\n","    }\n","    printf(\"\\n\");\n","\n","    printf(\"original: \");\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%.2f \", data2[i]);\n","    }\n","    printf(\"\\n\");\n","\n","    printf(\"  sorted: \");\n","    qsort(data2, SIZE, sizeof(double), compare_double);\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%.2f \", data2[i]);\n","    }\n","    printf(\"\\n\");\n","\n","    return 0;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"lS9pUaIN1Pxt","executionInfo":{"status":"ok","timestamp":1652794234019,"user_tz":-480,"elapsed":301,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"a174aa6a-f766-4f06-c22b-79cade2acb11"},"execution_count":106,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E14_03.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E14_03.c -o E14_03\n","./E14_03"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"9AhJVeEt1xrC","executionInfo":{"status":"ok","timestamp":1652794241689,"user_tz":-480,"elapsed":242,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"0f2fcdd7-19a9-41e6-978d-45feadf179f6"},"execution_count":107,"outputs":[{"output_type":"stream","name":"stdout","text":["original: 3 7 3 6 9 2 0 3 0 2 \n","  sorted: 9 7 6 3 3 3 2 2 0 0 \n","original: 0.39 0.80 0.20 0.77 0.55 0.63 0.51 0.92 0.72 0.61 \n","  sorted: 0.92 0.80 0.77 0.72 0.63 0.61 0.55 0.51 0.39 0.20 \n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":107}]},{"cell_type":"markdown","source":["## 對固定長度的字元陣列排序\n","\n","```C\n","#include <stdio.h>\n","#include <stdlib.h>\n","#include <string.h>\n","#define SIZE 10\n","\n","int compare(const void *a, const void *b)\n","{\n","    const char *da = (const char *) a;\n","    const char *db = (const char *) b;\n","    return strcmp(a, b);\n","}\n","\n","int main(void)\n","{\n","    char strs[SIZE][4] = {\n","        \"aab\", \"abc\", \"aaa\", \"abb\", \"acb\",\n","        \"aab\", \"abc\", \"aaa\", \"abb\", \"acb\"\n","    };\n","    int i;\n","\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%s\\n\", strs[i]);\n","    }\n","    printf(\"\\n\");\n","    qsort(strs, SIZE, 4*sizeof(char), compare);\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%s\\n\", strs[i]);\n","    }\n","\n","    return 0;\n","}\n","```\n","\n","上面的方法可以正確運作的原因是字串長度固定而且連續地被放置在記憶體中  \n","`strs[SIZE][4]`這個二維陣列的內容如下表，`strs[0]`對應到`\"aab\"`，`strs[1]`對應到`\"abc\"`  \n","但是其實這樣的二維陣列，在記憶體中仍然是用一維方式循序放置  \n","\n","memory          |   ptr[0]  |   ptr[1]  |   ptr[2]  |   ptr[3]\n","----------------|-----------|-----------|-----------|-----------\n","ptr = strs[0]   |   `'a'`   |   `'a'`   |   `'b'`   |   `'0'`    \n","ptr = strs[1]   |   `'a'`   |   `'b'`   |   `'c'`   |   `'0'`   \n","ptr = strs[2]   |   `'a'`   |   `'a'`   |   `'a'`   |   `'0'`   \n","ptr = strs[3]   |   `'a'`   |   `'b'`   |   `'b'`   |   `'0'`   \n","`...`           |   `...`   |   `...`   |   `...`   |   `...`    \n","\n","陣列總共有 10 個元素，每個陣列的元素包含 3 個英文字元外加後面跟著一個`'\\0'`字元 總共 4 bytes  \n","因此我們可以用`qsort(strs, SIZE, 4*sizeof(char), (int (*) (const void *, const void *))strcmp)`  \n","讓`qsort`以陣列元素為基本單位替我們排序，也就是以 4 bytes 為單位進行個別元素的比對與搬動  \n","最後`strs`的內容會直接被修改，並由小排到大  \n","\n","\n","## 對非固定長度的字串排序\n","\n","另一種方式，可以透過指標陣列，對不同長度的字串排序\n","\n","```C\n","#include <stdio.h>\n","#include <stdlib.h>\n","#include <string.h>\n","#define SIZE 10\n","\n","int compare_str_ptr(const void *a, const void *b)\n","{\n","    char **pa;\n","    char **pb;\n","    pa = (char **) a;\n","    pb = (char **) b;\n","    return strcmp(*pa, *pb);\n","}\n","\n","int main(void)\n","{\n","    char strs[SIZE][4] ={\n","        \"aab\", \"abc\", \"aaa\", \"abb\", \"acb\",\n","        \"aab\", \"abc\", \"aaa\", \"abb\", \"acb\"\n","    };\n","    char *ptrs[SIZE];\n","    int i;\n","\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%s\\n\", strs[i]);\n","    }\n","    printf(\"\\n\");\n","\n","\n","    for (i=0; i<SIZE; i++) {\n","        ptrs[i] = strs[i];\n","    }\n","    qsort(ptrs, SIZE, sizeof(char*), compare_str_ptr);\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%s\\n\", ptrs[i]);\n","    }\n","    printf(\"\\n\");\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%s\\n\", strs[i]);\n","    }\n","\n","\n","    return 0;\n","}\n","```\n","\n","`ptrs`是一個指標陣列  \n","因此`ptrs`的每個元素都是一個指標  都可以用來記錄某個記憶體位置  \n","我們先用`ptrs`的每個元素`ptrs[i]`分別記住每個字串的開始位址  \n","```C\n","for (i=0; i<SIZE; i++) {\n","    ptrs[i] = strs[i];\n","}\n","```\n","\n","接下來對指標陣列進行排序  \n","依照`ptrs`的每個元素所指到的字串用`strcmp`進行比較以後，將`ptrs`的元素搬動  \n","所以只是調換指標的順序 (也就是`ptrs`元素的順序)，實際的資料`strs`不會被更改  \n","\n","請注意這時候`compare`函數的寫法\n","\n","```C\n","int compare_str_ptr(const void *a, const void *b)\n","{\n","    char * *pa;\n","    char * *pb;\n","    pa = (char **) a;\n","    pb = (char **) b;\n","    return strcmp(*pa, *pb);\n","}\n","```\n","\n","*   被搬動的東西是指標\n","*   用來比較則是指標所指到的字串\n","\n","我們可以換個格式顯示陣列內容，執行底下附的程式碼會輸出下表的內容  \n","對照記憶體位址以及`strs`的內容就會看出端倪\n","\n","輸出  \n","\n","```\n","strs: aab0|abc0|aaa0|abb0|acb0|aab0|abc0|aaa0|abb0|acb0|\n","ptrs: 0028FEE4|0028FEE8|0028FEEC|0028FEF0|0028FEF4|0028FEF8|0028FEFC|0028FF00|0028FF04|0028FF08|\n","after sorting\n","ptrs: 0028FF00|0028FEEC|0028FEE4|0028FEF8|0028FEF0|0028FF04|0028FEE8|0028FEFC|0028FF08|0028FEF4|\n","ptrs: aaa0|aaa0|aab0|aab0|abb0|abb0|abc0|abc0|acb0|acb0|\n","strs: aab0|abc0|aaa0|abb0|acb0|aab0|abc0|aaa0|abb0|acb0|\n","```\n","\n","程式碼  \n","\n","```C\n","#include <stdio.h>\n","#include <stdlib.h>\n","#include <string.h>\n","#define SIZE 10\n","\n","int compare_str_ptr(const void *a, const void *b)\n","{\n","    char **pa;\n","    char **pb;\n","    pa = (char **) a;\n","    pb = (char **) b;\n","    return strcmp(*pa, *pb);\n","}\n","\n","int main(void)\n","{\n","    char strs[SIZE][4] ={\n","        \"aab\", \"abc\", \"aaa\", \"abb\", \"acb\",\n","        \"aab\", \"abc\", \"aaa\", \"abb\", \"acb\"\n","    };\n","    char *ptrs[SIZE];\n","    int i;\n","\n","    printf(\"strs: \");\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%s0|\", strs[i]);\n","    }\n","    printf(\"\\n\");\n","\n","    for (i=0; i<SIZE; i++) {\n","        ptrs[i] = strs[i];\n","    }\n","\n","    printf(\"ptrs: \");\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%p|\", ptrs[i]);\n","    }\n","    printf(\"\\nafter sorting\\n\");\n","\n","    qsort(ptrs, SIZE, sizeof(char*), compare_str_ptr);\n","\n","    printf(\"ptrs: \");\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%p|\", ptrs[i]);\n","    }\n","    printf(\"\\n\");\n","\n","    printf(\"ptrs: \");\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%s0|\", ptrs[i]);\n","    }\n","    printf(\"\\n\");\n","\n","    printf(\"strs: \");\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%s0|\", strs[i]);\n","    }\n","\n","    return 0;\n","}\n","```"],"metadata":{"id":"Syehx82N2OZp"}},{"cell_type":"code","source":["%%writefile E14_04.c\n","#include <stdio.h>\n","#include <stdlib.h>\n","#include <string.h>\n","#define SIZE 10\n","\n","int compare(const void *a, const void *b)\n","{\n","    const char *da = (const char *) a;\n","    const char *db = (const char *) b;\n","    return strcmp(a, b);\n","}\n","\n","int main(void)\n","{\n","    char strs[SIZE][4] = {\n","        \"aab\", \"abc\", \"aaa\", \"abb\", \"acb\",\n","        \"aab\", \"abc\", \"aaa\", \"abb\", \"acb\"\n","    };\n","    int i;\n","\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%s\\n\", strs[i]);\n","    }\n","    printf(\"\\n\");\n","    qsort(strs, SIZE, 4*sizeof(char), compare);\n","    for (i=0; i<SIZE; i++) {\n","        printf(\"%s\\n\", strs[i]);\n","    }\n","\n","    return 0;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"hz78i_TE7k9u","executionInfo":{"status":"ok","timestamp":1652739190892,"user_tz":-480,"elapsed":433,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"81401044-894c-4e09-b96f-23ab3baddfad"},"execution_count":3,"outputs":[{"output_type":"stream","name":"stdout","text":["Writing E14_04.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E14_04.c -o E14_04\n","./E14_04"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"yorO5mvE7rq3","executionInfo":{"status":"ok","timestamp":1652739219415,"user_tz":-480,"elapsed":293,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"01d03cd0-6fff-4991-ed3d-0b350301ecd5"},"execution_count":4,"outputs":[{"output_type":"stream","name":"stdout","text":["aab\n","abc\n","aaa\n","abb\n","acb\n","aab\n","abc\n","aaa\n","abb\n","acb\n","\n","aaa\n","aaa\n","aab\n","aab\n","abb\n","abb\n","abc\n","abc\n","acb\n","acb\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":4}]}]}