{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Week13.ipynb","provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyPPuUMIaJ3Sd8qdBtxp/UbB"},"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/程式設計一/Arrays](https://github.com/htchen/i2p-nthu/blob/master/%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88%E4%B8%80/array/array.md)\n","\n","\n","[https://github.com/htchen/i2p-nthu/tree/master/程式設計一/Pointers](https://github.com/htchen/i2p-nthu/blob/master/%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88%E4%B8%80/pointer/Pointer.md)\n"],"metadata":{"id":"05G1Fqg6GRZX"}},{"cell_type":"markdown","source":["##Example 1\n","###**複習上週內容**\n","###**指標與陣列**\n","\n","不同的指標 type，只用 ++ 符號時有什麼差別？"],"metadata":{"id":"mviKuWaapY32"}},{"cell_type":"code","source":["%%writefile E13_01.c\n","\n","#include <stdio.h>\n","int main(void)\n","{\n","  char data[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};\n","  char *p;\n","  int *q;\n","  long long *r;\n","\n","  p = data; \n","  q = (int*) data; \n","  r = (long long*) data;\n","  \n","  while (p < &data[12]) {\n","      printf(\"%p %x\\n\", p, *p);\n","      ++p;\n","  }\n","  printf(\"\\n\");\n","  while (q < (int*)&data[12]) {\n","      printf(\"%p %08x\\n\", q, *q);\n","      ++q;\n","  }\n","  printf(\"\\n\");\n","  while (r < (long long*)&data[12]) {\n","      printf(\"%p %016llx\\n\", r, *r);\n","      ++r;\n","  }\n","\n","  return 0;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"7ZODSFC-pmP2","executionInfo":{"status":"ok","timestamp":1652181111221,"user_tz":-480,"elapsed":310,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"667f6ba1-aa2b-41ed-fc3e-22e1daf97df6"},"execution_count":86,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E13_01.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E13_01.c -o E13_01\n","./E13_01\n"],"metadata":{"id":"HMqFdYymQIzj","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652181115378,"user_tz":-480,"elapsed":329,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"d4ba0849-6b14-400b-8d06-d385cde34a5e"},"execution_count":87,"outputs":[{"output_type":"stream","name":"stdout","text":["0x7fffc308ffa0 1\n","0x7fffc308ffa1 2\n","0x7fffc308ffa2 3\n","0x7fffc308ffa3 4\n","0x7fffc308ffa4 5\n","0x7fffc308ffa5 6\n","0x7fffc308ffa6 7\n","0x7fffc308ffa7 8\n","0x7fffc308ffa8 9\n","0x7fffc308ffa9 a\n","0x7fffc308ffaa b\n","0x7fffc308ffab c\n","\n","0x7fffc308ffa0 04030201\n","0x7fffc308ffa4 08070605\n","0x7fffc308ffa8 0c0b0a09\n","\n","0x7fffc308ffa0 0807060504030201\n","0x7fffc308ffa8 000000000c0b0a09\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":87}]},{"cell_type":"markdown","source":["##Example 2\n","## 等價的寫法\n","`a[i]`  ⟺ `*(a+i)`\n","\n","`&a[i]`  ⟺ `(a+i)`"],"metadata":{"id":"Mp5lAOxDodYd"}},{"cell_type":"code","source":["%%writefile E13_02.c\n","#include <stdio.h>\n","\n","#include <stdio.h>\n","int main(void)\n","{\n","  char data[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};\n","  char *p;\n","  int i;\n","\n","  p = data;\n","\n","  i = 0;\n","  while (p < data+12) {\n","      printf(\"%p %d\\n\", p, *p);\n","      ++p;\n","  }\n","\n","  return 0;\n","}\n"],"metadata":{"id":"LZ8575uZo5hG","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652181634388,"user_tz":-480,"elapsed":318,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"7bab453b-2cba-4995-e694-fef68e959544"},"execution_count":96,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E13_02.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E13_02.c -o E13_02\n","./E13_02\n"],"metadata":{"id":"f1ClwjOzsdsQ","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652181645991,"user_tz":-480,"elapsed":460,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"b2d0cce1-90c5-47fb-8414-5b08e5c68204"},"execution_count":97,"outputs":[{"output_type":"stream","name":"stdout","text":["0x7ffd89bb73bc 1\n","0x7ffd89bb73bd 2\n","0x7ffd89bb73be 3\n","0x7ffd89bb73bf 4\n","0x7ffd89bb73c0 5\n","0x7ffd89bb73c1 6\n","0x7ffd89bb73c2 7\n","0x7ffd89bb73c3 8\n","0x7ffd89bb73c4 9\n","0x7ffd89bb73c5 10\n","0x7ffd89bb73c6 11\n","0x7ffd89bb73c7 12\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":97}]},{"cell_type":"markdown","source":["## 上週 Exercise 2\n","\n","自己寫一個可以計算字串長度的函數\n","```\n","  unsigned long mylen(char *str);\n","```"],"metadata":{"id":"4O77IJid6e78"}},{"cell_type":"code","source":["%%writefile W12_02.c\n","#include <stdio.h>\n","\n","unsigned long mylen(char *str);\n","\n","int main(void)\n","{\n","  char str[100];\n","  scanf(\"%99s\", str);\n","  printf(\"%lu, %s\\n\", mylen(str), str);\n"," \n","  return 0;\n","}\n","\n","unsigned long mylen(char *p) \n","{\n","  char *q = p;\n","\n","  while (*p != '\\0') {\n","      ++p; \n","  }\n","  return p-q;\n","}\n"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"roozgTUc6HGU","executionInfo":{"status":"ok","timestamp":1652182707803,"user_tz":-480,"elapsed":306,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"80248874-766d-49f2-a82e-eceb9b8e9ea0"},"execution_count":102,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting W12_02.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc W12_02.c -o W12_02\n","./W12_02"],"metadata":{"id":"lV3FoloM7Cbh","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652182719719,"user_tz":-480,"elapsed":9074,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"4171072f-f320-47ac-d2ca-b69f8a898249"},"execution_count":103,"outputs":[{"output_type":"stream","name":"stdout","text":["abcdef\n","6, abcdef\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":103}]},{"cell_type":"markdown","source":["##Example 3\n","\n","\n","Download files:\n","\n","[data_50000.txt](https://drive.google.com/uc?id=1XapeYR19tJaP5mrxQA8RkfWZdIBouKfc)\n","\n","[test.txt](https://drive.google.com/uc?id=1yI6-IajsjRMH_bSOVdvs1e1oSdo9rFfy)\n","\n","\n","\n"],"metadata":{"id":"2HgZZI7vpHFE"}},{"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":122,"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":123,"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 4\n","\n","###**二維陣列**\n","\n","對電腦程式來說，二維陣列是非常方便的資料儲存和表示方式，例如數位影像或矩陣，本身就具有二維特性，如果要對影像或矩陣做處理，使用二維陣列的方式來操作在思考上會比較直接。在 C 程式裡要產生一個二維陣列的寫法是\n","```\n","int a[3][4];\n","```\n","\n","```\n","-----------------------------------------\n","| a[0][0] | a[0][1] | a[0][2] | a[0][3] |\n","-----------------------------------------\n","| a[1][0] | a[1][1] | a[1][2] | a[1][3] |\n","-----------------------------------------\n","| a[2][0] | a[2][1] | a[2][2] | a[2][3] |\n","-----------------------------------------\n","```\n","\n","如果要設定初值，則可以用下面的方式來設定\n","```\n","int a[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };\n","```\n","或是\n","```\n","int a[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };\n","```\n","\n","上面的例子傳達的一個觀念是，雖然我們把資料排列方式想像成二維，但是實際上電腦是用循序的方式來儲存資料，所以其實就只是一維，也就是說每個二維陣列裡的資料是一列接著一列放置在記憶體裡。使用二維陣列表示法只是為了方便我們在寫程式時可以用比較直觀的方式思考。\n","\n","\n","依照設定一維陣列初始值的規則，推廣到二維陣列。底下的程式碼會得到什麼結果。\n","```\n","int a[][4] = { {1, 2, 3, 4}, {5, 6}, {9, 10, 11, 12}};\n","int b[][4] = { 1, 2, 3, 4, 5, 6, 9, 10, 11, 12};\n","```"],"metadata":{"id":"7co6TxbjrUL2"}},{"cell_type":"markdown","source":["底下的程式碼用 `sizeof` 來顯示出二維陣列的大小，從輸出結果可以看出 `sizeof(a[0])` 的大小相當於 `sizeof(int)*4`，而 `sizeof(a)` 的大小則相當於 `sizeof(a[0])*3`，也就是 `sizeof(int)*4*3`。下面的程式碼同時也顯示了不同的初始化的結果。\n"],"metadata":{"id":"zApIumfMf6db"}},{"cell_type":"code","source":["%%writefile E13_04.c\n","#include<stdio.h>\n","int main(void)\n","{\n","   int a[][4] = { {1, 2, 3, 4}, {5, 6}, {9, 10, 11, 12}};\n","   int b[][4] = { 1, 2, 3, 4, 5, 6, 9, 10, 11, 12};\n","\n","   int i, j;\n"," \n","   printf(\"a:       %lu bytes\\n\", sizeof(a));\n","   printf(\"a[0]:    %lu bytes\\n\", sizeof(a[0]));\n","   printf(\"a[0][0]: %lu bytes\\n\", sizeof(a[0][0]));\n","   \n","   printf(\"\\n\");\n","   for (i=0; i<3; i++) {\n","      for (j=0; j<4; j++) {\n","         printf(\"%3d \", a[i][j]);\n","      }\n","      printf(\"\\n\");\n","   }\n","   printf(\"\\n\");\n","   for (i=0; i<3; i++) {\n","      for (j=0; j<4; j++) {\n","         printf(\"%3d \", b[i][j]);\n","      }\n","      printf(\"\\n\");\n","   }\n","   \n","   return 0;\n","}"],"metadata":{"id":"bNrwKmsysNfy","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652184411352,"user_tz":-480,"elapsed":321,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"1a65e31e-a224-4e95-ee07-b61b60a3e348"},"execution_count":124,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E13_04.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc E13_04.c -o E13_04\n","./E13_04"],"metadata":{"id":"puvNtlHWssLK","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1652184416407,"user_tz":-480,"elapsed":323,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"79baca67-a1f2-41ce-a357-279f9ca1f9db"},"execution_count":125,"outputs":[{"output_type":"stream","name":"stdout","text":["a:       48 bytes\n","a[0]:    16 bytes\n","a[0][0]: 4 bytes\n","\n","  1   2   3   4 \n","  5   6   0   0 \n","  9  10  11  12 \n","\n","  1   2   3   4 \n","  5   6   9  10 \n"," 11  12   0   0 \n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":125}]},{"cell_type":"markdown","source":["另外一種看待二維陣列的方式是把它想成 \"陣列的陣列\"：\n","```\n","typedef int row_vector [5];\n","row_vector matrix[4];\n","```\n","上面的程式碼相當於\n","```\n","int matrix[4][5];\n","```\n","也就是說， `row_vector` 是一種包含五個元素的陣列，把這樣的東西用 `typedef` 定成一種新的型別，然後 `matrix` 就是一個由四個 `row_vector` 組成的陣列。"],"metadata":{"id":"zI9rD5DOhAZ3"}},{"cell_type":"markdown","source":["\n","###**指標注意**\n","\n","有一個必須牢記在心的重點：**未做初始化的指標，絕對不能對牠做 dereferencing**。這一個重點很有可能一不小心會沒有注意到。例如底下的程式碼，先想想看會有什麼問題：\n","```\n","int *pt;\n","int data[10];\n","pt = data;\n","*pt = 5;\n","```\n","\n","乍看之下似乎沒什麼問題，但是我們想要把 `pt` 所指到的位址裡面放入整數 `5`，那麼 `pt` 目前指到的位址在哪裡呢？答案是不確定。當我們宣告一個指標變數的時候，我們只會得到一個可以用來記錄記憶體位址的變數，至於牠所記錄的記憶體位址究竟在哪裡，以及那個位址是否可以被使用，都必須等到我們做了額外的動作之後才能確定。總之，一定要牢記並遵守指標初始化的原則，對於未初始化的指標，絕對不要對牠使用 `*` 符號來修改記憶體內容。\n","\n","https://www.youtube.com/watch?v=mnXkiAKbUPg"],"metadata":{"id":"eAEfEJkitIw9"}},{"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"," 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":126,"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":127,"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","int main(void)\n","{\n","  char z[4][3] = {{'A', 'B', 'C'}, {'D', 'E', 'F'}};\n","  char (*p) [3];\n","  p = z;\n","/*\n"," a[i] ⟺ *(a+i)\n","&a[i] ⟺ (a+i)\n"," */\n","  printf(\"p+0: %p\\n\", p+0); // \n","  printf(\"p+1: %p\\n\", p+1); // \n","  printf(\"p+2: %p\\n\", p+2); // \n","  printf(\"z+0: %p\\n\", z+0); // &z[0]\n","  printf(\"z+1: %p\\n\", z+1); // &z[1] \n","  printf(\"z+2: %p\\n\", z+2); // &z[2]\n","\n","  return 0;\n","}"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"9qGmVTd-DNDR","executionInfo":{"status":"ok","timestamp":1652189331031,"user_tz":-480,"elapsed":334,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"fbc97b4f-7d73-4449-fb0c-b76ddb0cc12e"},"execution_count":144,"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":1652189335931,"user_tz":-480,"elapsed":305,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"34bf464e-c780-44a1-f4d3-7d824cd22673"},"execution_count":145,"outputs":[{"output_type":"stream","name":"stdout","text":["p+0: 0x7ffdc5294aac\n","p+1: 0x7ffdc5294aaf\n","p+2: 0x7ffdc5294ab2\n","z+0: 0x7ffdc5294aac\n","z+1: 0x7ffdc5294aaf\n","z+2: 0x7ffdc5294ab2\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":145}]},{"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":1651582501581,"user_tz":-480,"elapsed":259,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"0bef9afe-70f9-4a10-cdee-3e09263dcda4"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting W12_01.c\n"]}]},{"cell_type":"code","source":["%%shell\n","gcc W12_01.c -o W12_01\n","./W12_01"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"s4HVR61NvjWu","executionInfo":{"status":"ok","timestamp":1651582506397,"user_tz":-480,"elapsed":271,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"e59942c4-b763-4538-ffe5-cf8ff1fbbef9"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["101 501\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":81}]},{"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":53,"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":54,"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 E13_07.c\n"],"metadata":{"id":"D_NvYNQnvOPt"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["%%shell\n","gcc W13_02.c -o W13_02\n","./W13_08"],"metadata":{"id":"xSfXl-Q1vzgq"},"execution_count":null,"outputs":[]},{"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 a[] = \"cat\";\n","   permutation(a, 3);\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":1652148784021,"user_tz":-480,"elapsed":329,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"83de2374-b227-4a34-ef68-f00bce1e8bbb"},"execution_count":59,"outputs":[{"output_type":"stream","name":"stdout","text":["Overwriting E13_08.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":1652148788012,"user_tz":-480,"elapsed":301,"user":{"displayName":"HT Chen","userId":"17748361917871513601"}},"outputId":"a785e6eb-621e-4c22-995b-817b47798cc2"},"execution_count":60,"outputs":[{"output_type":"stream","name":"stdout","text":["atc\n","tac\n","tca\n","cta\n","act\n","cat\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":60}]}]}